comparison src/lread.c @ 4921:17362f371cc2

add more byte-code assertions and better failure output -------------------- ChangeLog entries follow: -------------------- src/ChangeLog addition: 2010-02-03 Ben Wing <ben@xemacs.org> * alloc.c (Fmake_byte_code): * bytecode.h: * lisp.h: * lread.c: * lread.c (readevalloop): * lread.c (Fread): * lread.c (Fread_from_string): * lread.c (read_list_conser): * lread.c (read_list): * lread.c (vars_of_lread): * symbols.c: * symbols.c (Fdefine_function): Turn on the "compiled-function annotation hack". Implement it properly by hooking into Fdefalias(). Note in the docstring to `defalias' that we do this. Remove some old broken code and change code that implemented the old kludgy way of hooking into the Lisp reader into bracketed by `#ifdef COMPILED_FUNCTION_ANNOTATION_HACK_OLD_WAY', which is not enabled. Also enable byte-code metering when DEBUG_XEMACS -- this is a form of profiling for computing histograms of which sequences of two bytecodes are used most often. * bytecode-ops.h: * bytecode-ops.h (OPCODE): New file. Extract out all the opcodes and declare them using OPCODE(), a bit like frame slots and such. This way the file can be included multiple times if necessary to iterate multiple times over the byte opcodes. * bytecode.c: * bytecode.c (NUM_REMEMBERED_BYTE_OPS): * bytecode.c (OPCODE): * bytecode.c (assert_failed_with_remembered_ops): * bytecode.c (READ_UINT_2): * bytecode.c (READ_INT_1): * bytecode.c (READ_INT_2): * bytecode.c (PEEK_INT_1): * bytecode.c (PEEK_INT_2): * bytecode.c (JUMP_RELATIVE): * bytecode.c (JUMP_NEXT): * bytecode.c (PUSH): * bytecode.c (POP_WITH_MULTIPLE_VALUES): * bytecode.c (DISCARD): * bytecode.c (UNUSED): * bytecode.c (optimize_byte_code): * bytecode.c (optimize_compiled_function): * bytecode.c (Fbyte_code): * bytecode.c (vars_of_bytecode): * bytecode.c (init_opcode_table_multi_op): * bytecode.c (reinit_vars_of_bytecode): * emacs.c (main_1): * eval.c (funcall_compiled_function): * symsinit.h: Any time we change either the instruction pointer or the stack pointer, assert that we're going to move it to a valid location. This should catch failures right when they occur rather than sometime later. This requires that we pass in another couple of parameters into some functions (only with error-checking enabled, see below). Also keep track, using a circular queue, of the last 100 byte opcodes seen, and when we hit an assert failure during byte-code execution, output the contents of the queue in a nice readable fashion. This requires that bytecode-ops.h be included a second time so that a table mapping opcodes to the name of their operation can be constructed. This table is constructed in new function reinit_vars_of_bytecode(). Everything in the last two paras happens only when ERROR_CHECK_BYTE_CODE. Add some longish comments describing how the arrays that hold the stack and instructions, and the pointers used to access them, work. * gc.c: Import some code from my `latest-fix' workspace to mark the staticpro's in order from lowest to highest, rather than highest to lowest, so it's easier to debug when something goes wrong. * lisp.h (abort_with_message): Renamed from abort_with_msg(). * symbols.c (defsymbol_massage_name_1): * symbols.c (defsymbol_nodump): * symbols.c (defsymbol): * symbols.c (defkeyword): * symeval.h (DEFVAR_SYMVAL_FWD_OBJECT): Make the various calls to staticpro() instead call staticpro_1(), passing in the name of the C var being staticpro'ed, so that it shows up in staticpro_names. Otherwise staticpro_names just has 1000+ copies of the word `location'.
author Ben Wing <ben@xemacs.org>
date Wed, 03 Feb 2010 08:01:55 -0600
parents 91b3d00e717f
children 8ee3c10d1ed5
comparison
equal deleted inserted replaced
4914:1628e3b9601a 4921:17362f371cc2
1 /* Lisp parsing and input streams. 1 /* Lisp parsing and input streams.
2 Copyright (C) 1985-1989, 1992-1995 Free Software Foundation, Inc. 2 Copyright (C) 1985-1989, 1992-1995 Free Software Foundation, Inc.
3 Copyright (C) 1995 Tinker Systems. 3 Copyright (C) 1995 Tinker Systems.
4 Copyright (C) 1996, 2001, 2002, 2003 Ben Wing. 4 Copyright (C) 1996, 2001, 2002, 2003, 2010 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
146 static Lisp_Object Vload_force_doc_string_list; 146 static Lisp_Object Vload_force_doc_string_list;
147 147
148 /* A resizing-buffer stream used to temporarily hold data while reading */ 148 /* A resizing-buffer stream used to temporarily hold data while reading */
149 static Lisp_Object Vread_buffer_stream; 149 static Lisp_Object Vread_buffer_stream;
150 150
151 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK 151 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK_OLD_WAY
152 /* The stuff throughout this file that sets the following variable is
153 concerned with old-style .elc files that set up compiled functions using
154
155 (fset 'fun #[... ...])
156
157 Where #[... ...] is a literal compiled-function object. We want the
158 name of the function to get stored as the annotation, so in a clever but
159 nastily kludgy fashion, we hack the code that reads lists so that if it
160 sees a symbol `fset' as the first argument, it stores the second argument
161 in Vcurrent_compiled_function_annotation, and then when the third
162 argument gets read and a compiled-function object created by a call to
163 Fmake_byte_code(), the stored annotation will get snarfed up. Elsewhere,
164 we reset Vcurrent_compiled_function_annotation to nil so it's not still
165 defined in case we have a #[... ...] in other circumstances -- in that
166 case we use the filename (Vload_file_name_internal).
167
168 Now it's arguable that I should simply have hacked Ffset()
169 appropriately. This is all moot, however, be nowadays calls that set up
170 compiled functions look like
171
172 (defalias 'fun #[... ...])
173
174 Where Fdefalias is like Ffset but sets up load-history for the function.
175 Hence it's exactly the right place to hack, and it's not even messy.
176
177 When we're sure the annotation mechanism works the new way, delete all
178 this old nasty code.
179
180 --ben 2-2-10 */
152 Lisp_Object Vcurrent_compiled_function_annotation; 181 Lisp_Object Vcurrent_compiled_function_annotation;
153 #endif 182 #endif
154 183
155 static int load_byte_code_version; 184 static int load_byte_code_version;
156 185
1449 READCHARFUN (which can be a stream) to Lisp. --hniksic */ 1478 READCHARFUN (which can be a stream) to Lisp. --hniksic */
1450 /*specbind (Qstandard_input, readcharfun);*/ 1479 /*specbind (Qstandard_input, readcharfun);*/
1451 1480
1452 internal_bind_lisp_object (&Vcurrent_load_list, Qnil); 1481 internal_bind_lisp_object (&Vcurrent_load_list, Qnil);
1453 1482
1454 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK 1483 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK_OLD_WAY
1455 Vcurrent_compiled_function_annotation = Qnil; 1484 Vcurrent_compiled_function_annotation = Qnil;
1456 #endif 1485 #endif
1457 GCPRO2 (val, sourcename); 1486 GCPRO2 (val, sourcename);
1458 1487
1459 LOADHIST_ATTACH (sourcename); 1488 LOADHIST_ATTACH (sourcename);
1617 if (EQ (stream, Qt)) 1646 if (EQ (stream, Qt))
1618 stream = Qread_char; 1647 stream = Qread_char;
1619 1648
1620 Vread_objects = Qnil; 1649 Vread_objects = Qnil;
1621 1650
1622 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK 1651 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK_OLD_WAY
1623 Vcurrent_compiled_function_annotation = Qnil; 1652 Vcurrent_compiled_function_annotation = Qnil;
1624 #endif 1653 #endif
1625 if (EQ (stream, Qread_char)) 1654 if (EQ (stream, Qread_char))
1626 { 1655 {
1627 Lisp_Object val = call1 (Qread_from_minibuffer, 1656 Lisp_Object val = call1 (Qread_from_minibuffer,
1646 Bytecount startval, endval; 1675 Bytecount startval, endval;
1647 Lisp_Object tem; 1676 Lisp_Object tem;
1648 Lisp_Object lispstream = Qnil; 1677 Lisp_Object lispstream = Qnil;
1649 struct gcpro gcpro1; 1678 struct gcpro gcpro1;
1650 1679
1651 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK 1680 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK_OLD_WAY
1652 Vcurrent_compiled_function_annotation = Qnil; 1681 Vcurrent_compiled_function_annotation = Qnil;
1653 #endif 1682 #endif
1654 GCPRO1 (lispstream); 1683 GCPRO1 (lispstream);
1655 CHECK_STRING (string); 1684 CHECK_STRING (string);
1656 get_string_range_byte (string, start, end, &startval, &endval, 1685 get_string_range_byte (string, start, end, &startval, &endval,
3007 } 3036 }
3008 read_syntax_error (". in wrong context"); 3037 read_syntax_error (". in wrong context");
3009 } 3038 }
3010 } 3039 }
3011 3040
3012 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK 3041 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK_OLD_WAY
3013 if (s->length == 1 && s->allow_dotted_lists && EQ (XCAR (s->head), Qfset)) 3042 if (s->length == 1 && s->allow_dotted_lists && EQ (XCAR (s->head), Qfset))
3014 { 3043 {
3015 if (CONSP (elt) && EQ (XCAR (elt), Qquote) && CONSP (XCDR (elt))) 3044 if (CONSP (elt) && EQ (XCAR (elt), Qquote) && CONSP (XCDR (elt)))
3016 Vcurrent_compiled_function_annotation = XCAR (XCDR (elt)); 3045 Vcurrent_compiled_function_annotation = XCAR (XCDR (elt));
3017 else 3046 else
3052 int allow_dotted_lists, 3081 int allow_dotted_lists,
3053 int check_for_doc_references) 3082 int check_for_doc_references)
3054 { 3083 {
3055 struct read_list_state s; 3084 struct read_list_state s;
3056 struct gcpro gcpro1, gcpro2; 3085 struct gcpro gcpro1, gcpro2;
3057 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK 3086 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK_OLD_WAY
3058 Lisp_Object old_compiled_function_annotation = 3087 Lisp_Object old_compiled_function_annotation =
3059 Vcurrent_compiled_function_annotation; 3088 Vcurrent_compiled_function_annotation;
3060 #endif 3089 #endif
3061 3090
3062 s.head = Qnil; 3091 s.head = Qnil;
3065 s.allow_dotted_lists = allow_dotted_lists; 3094 s.allow_dotted_lists = allow_dotted_lists;
3066 s.terminator = terminator; 3095 s.terminator = terminator;
3067 GCPRO2 (s.head, s.tail); 3096 GCPRO2 (s.head, s.tail);
3068 3097
3069 sequence_reader (readcharfun, terminator, &s, read_list_conser); 3098 sequence_reader (readcharfun, terminator, &s, read_list_conser);
3070 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK 3099 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK_OLD_WAY
3071 Vcurrent_compiled_function_annotation = old_compiled_function_annotation; 3100 Vcurrent_compiled_function_annotation = old_compiled_function_annotation;
3072 #endif 3101 #endif
3073 3102
3074 if ((purify_flag || load_force_doc_strings) && check_for_doc_references) 3103 if ((purify_flag || load_force_doc_strings) && check_for_doc_references)
3075 { 3104 {
3475 staticpro (&Vload_force_doc_string_list); 3504 staticpro (&Vload_force_doc_string_list);
3476 3505
3477 Vload_file_name_internal = Qnil; 3506 Vload_file_name_internal = Qnil;
3478 staticpro (&Vload_file_name_internal); 3507 staticpro (&Vload_file_name_internal);
3479 3508
3480 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK 3509 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK_OLD_WAY
3481 Vcurrent_compiled_function_annotation = Qnil; 3510 Vcurrent_compiled_function_annotation = Qnil;
3482 staticpro (&Vcurrent_compiled_function_annotation); 3511 staticpro (&Vcurrent_compiled_function_annotation);
3483 #endif 3512 #endif
3484 3513
3485 /* So that early-early stuff will work */ 3514 /* So that early-early stuff will work */