X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/3e21b6a72b87787e2327513a44623b250054f77d..14af5f7fc4d7557ee712d3b6a8b46d9034c2ff39:/src/bytecode.c diff --git a/src/bytecode.c b/src/bytecode.c index b2e9e3c5b5..6f945723d3 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -1,5 +1,5 @@ /* Execution of byte code produced by bytecomp.el. - Copyright (C) 1985-1988, 1993, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1985-1988, 1993, 2000-2012 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -51,7 +51,7 @@ by Hallvard: * * define BYTE_CODE_METER to enable generation of a byte-op usage histogram. */ -#define BYTE_CODE_SAFE +/* #define BYTE_CODE_SAFE */ /* #define BYTE_CODE_METER */ @@ -76,15 +76,10 @@ Lisp_Object Qbyte_code_meter; } \ } -#else /* no BYTE_CODE_METER */ - -#define METER_CODE(last_code, this_code) - -#endif /* no BYTE_CODE_METER */ +#endif /* BYTE_CODE_METER */ Lisp_Object Qbytecode; -extern Lisp_Object Qand_optional, Qand_rest; /* Byte codes: */ @@ -148,7 +143,9 @@ extern Lisp_Object Qand_optional, Qand_rest; #define Bpreceding_char 0150 #define Bcurrent_column 0151 #define Bindent_to 0152 -#define Bscan_buffer 0153 /* No longer generated as of v18 */ +#ifdef BYTE_CODE_SAFE +#define Bscan_buffer 0153 /* No longer generated as of v18. */ +#endif #define Beolp 0154 #define Beobp 0155 #define Bbolp 0156 @@ -156,9 +153,13 @@ extern Lisp_Object Qand_optional, Qand_rest; #define Bcurrent_buffer 0160 #define Bset_buffer 0161 #define Bsave_current_buffer_1 0162 /* Replacing Bsave_current_buffer. */ +#if 0 #define Bread_char 0162 /* No longer generated as of v19 */ +#endif +#ifdef BYTE_CODE_SAFE #define Bset_mark 0163 /* this loser is no longer generated as of v18 */ -#define Binteractive_p 0164 /* Obsolete. */ +#endif +#define Binteractive_p 0164 /* Obsolete since Emacs-24.1. */ #define Bforward_char 0165 #define Bforward_word 0166 @@ -183,16 +184,16 @@ extern Lisp_Object Qand_optional, Qand_rest; #define Bdup 0211 #define Bsave_excursion 0212 -#define Bsave_window_excursion 0213 /* Obsolete. */ +#define Bsave_window_excursion 0213 /* Obsolete since Emacs-24.1. */ #define Bsave_restriction 0214 #define Bcatch 0215 #define Bunwind_protect 0216 #define Bcondition_case 0217 -#define Btemp_output_buffer_setup 0220 /* Obsolete. */ -#define Btemp_output_buffer_show 0221 /* Obsolete. */ +#define Btemp_output_buffer_setup 0220 /* Obsolete since Emacs-24.1. */ +#define Btemp_output_buffer_show 0221 /* Obsolete since Emacs-24.1. */ -#define Bunbind_all 0222 /* Obsolete. */ +#define Bunbind_all 0222 /* Obsolete. Never used. */ #define Bset_marker 0223 #define Bmatch_beginning 0224 @@ -234,8 +235,9 @@ extern Lisp_Object Qand_optional, Qand_rest; #define BdiscardN 0266 #define Bconstant 0300 -#define CONSTANTLIM 0100 +/* Whether to maintain a `top' and `bottom' field in the stack frame. */ +#define BYTE_MAINTAIN_TOP (BYTE_CODE_SAFE || BYTE_MARK_STACK) /* Structure describing a value stack used during byte-code execution in Fbyte_code. */ @@ -248,7 +250,9 @@ struct byte_stack /* Top and bottom of stack. The bottom points to an area of memory allocated with alloca in Fbyte_code. */ +#if BYTE_MAINTAIN_TOP Lisp_Object *top, *bottom; +#endif /* The string containing the byte-code, and its current address. Storing this here protects it from GC because mark_byte_stack @@ -267,7 +271,7 @@ struct byte_stack /* A list of currently active byte-code execution value stacks. Fbyte_code adds an entry to the head of this list before it starts processing byte-code, and it removed the entry again when it is - done. Signalling an error truncates the list analoguous to + done. Signaling an error truncates the list analogous to gcprolist. */ struct byte_stack *byte_stack_list; @@ -275,6 +279,7 @@ struct byte_stack *byte_stack_list; /* Mark objects on byte_stack_list. Called during GC. */ +#if BYTE_MARK_STACK void mark_byte_stack (void) { @@ -299,7 +304,7 @@ mark_byte_stack (void) mark_object (stack->constants); } } - +#endif /* Unmark objects in the stacks on byte_stack_list. Relocate program counters. Called when GC has completed. */ @@ -353,13 +358,19 @@ unmark_byte_stack (void) /* Actions that must be performed before and after calling a function that might GC. */ +#if !BYTE_MAINTAIN_TOP +#define BEFORE_POTENTIAL_GC() ((void)0) +#define AFTER_POTENTIAL_GC() ((void)0) +#else #define BEFORE_POTENTIAL_GC() stack.top = top #define AFTER_POTENTIAL_GC() stack.top = NULL +#endif /* Garbage collect if we have consed enough since the last time. We do this at every branch, to avoid loops that never GC. */ #define MAYBE_GC() \ + do { \ if (consing_since_gc > gc_cons_threshold \ && consing_since_gc > gc_relative_threshold) \ { \ @@ -367,7 +378,7 @@ unmark_byte_stack (void) Fgarbage_collect (); \ AFTER_POTENTIAL_GC (); \ } \ - else + } while (0) /* Check for jumping out of range. */ @@ -401,24 +412,15 @@ unmark_byte_stack (void) } while (0) -DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, MANY, 0, +DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0, doc: /* Function used internally in byte-compiled code. The first argument, BYTESTR, is a string of byte code; the second, VECTOR, a vector of constants; the third, MAXDEPTH, the maximum stack depth used in this function. -If the third argument is incorrect, Emacs may crash. - -If ARGS-TEMPLATE is specified, it is an argument list specification, -according to which any remaining arguments are pushed on the stack -before executing BYTESTR. - -usage: (byte-code BYTESTR VECTOR MAXDEP &optional ARGS-TEMPLATE &rest ARGS) */) - (int nargs, Lisp_Object *args) +If the third argument is incorrect, Emacs may crash. */) + (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth) { - Lisp_Object args_tmpl = nargs >= 4 ? args[3] : Qnil; - int pnargs = nargs >= 4 ? nargs - 4 : 0; - Lisp_Object *pargs = nargs >= 4 ? args + 4 : 0; - return exec_byte_code (args[0], args[1], args[2], args_tmpl, pnargs, pargs); + return exec_byte_code (bytestr, vector, maxdepth, Qnil, 0, NULL); } /* Execute the byte-code in BYTESTR. VECTOR is the constant vector, and @@ -431,7 +433,7 @@ usage: (byte-code BYTESTR VECTOR MAXDEP &optional ARGS-TEMPLATE &rest ARGS) */) Lisp_Object exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, - Lisp_Object args_template, int nargs, Lisp_Object *args) + Lisp_Object args_template, ptrdiff_t nargs, Lisp_Object *args) { int count = SPECPDL_INDEX (); #ifdef BYTE_CODE_METER @@ -442,10 +444,10 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, /* Lisp_Object v1, v2; */ Lisp_Object *vectorp; #ifdef BYTE_CODE_SAFE - int const_length = XVECTOR (vector)->size; + ptrdiff_t const_length; Lisp_Object *stacke; -#endif int bytestr_length; +#endif struct byte_stack stack; Lisp_Object *top; Lisp_Object result; @@ -462,7 +464,11 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, CHECK_STRING (bytestr); CHECK_VECTOR (vector); - CHECK_NUMBER (maxdepth); + CHECK_NATNUM (maxdepth); + +#ifdef BYTE_CODE_SAFE + const_length = ASIZE (vector); +#endif if (STRING_MULTIBYTE (bytestr)) /* BYTESTR must have been produced by Emacs 20.2 or the earlier @@ -472,16 +478,23 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, convert them back to the originally intended unibyte form. */ bytestr = Fstring_as_unibyte (bytestr); +#ifdef BYTE_CODE_SAFE bytestr_length = SBYTES (bytestr); +#endif vectorp = XVECTOR (vector)->contents; stack.byte_string = bytestr; stack.pc = stack.byte_string_start = SDATA (bytestr); stack.constants = vector; - stack.bottom = (Lisp_Object *) alloca (XFASTINT (maxdepth) + if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (Lisp_Object) < XFASTINT (maxdepth)) + memory_full (SIZE_MAX); + top = (Lisp_Object *) alloca (XFASTINT (maxdepth) * sizeof (Lisp_Object)); - top = stack.bottom - 1; +#if BYTE_MAINTAIN_TOP + stack.bottom = top; stack.top = NULL; +#endif + top -= 1; stack.next = byte_stack_list; byte_stack_list = &stack; @@ -489,37 +502,50 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, stacke = stack.bottom - 1 + XFASTINT (maxdepth); #endif - if (! NILP (args_template)) - /* We should push some arguments on the stack. */ + if (INTEGERP (args_template)) { - Lisp_Object at; - int pushed = 0, optional = 0; - - for (at = args_template; CONSP (at); at = XCDR (at)) - if (EQ (XCAR (at), Qand_optional)) - optional = 1; - else if (EQ (XCAR (at), Qand_rest)) - { - PUSH (pushed < nargs - ? Flist (nargs - pushed, args) - : Qnil); - pushed = nargs; - at = Qnil; - break; - } - else if (pushed < nargs) - { - PUSH (*args++); - pushed++; - } - else if (optional) - PUSH (Qnil); - else - break; - - if (pushed != nargs || !NILP (at)) + ptrdiff_t at = XINT (args_template); + int rest = at & 128; + int mandatory = at & 127; + ptrdiff_t nonrest = at >> 8; + eassert (mandatory <= nonrest); + if (nargs <= nonrest) + { + ptrdiff_t i; + for (i = 0 ; i < nargs; i++, args++) + PUSH (*args); + if (nargs < mandatory) + /* Too few arguments. */ + Fsignal (Qwrong_number_of_arguments, + Fcons (Fcons (make_number (mandatory), + rest ? Qand_rest : make_number (nonrest)), + Fcons (make_number (nargs), Qnil))); + else + { + for (; i < nonrest; i++) + PUSH (Qnil); + if (rest) + PUSH (Qnil); + } + } + else if (rest) + { + ptrdiff_t i; + for (i = 0 ; i < nonrest; i++, args++) + PUSH (*args); + PUSH (Flist (nargs - nonrest, args)); + } + else + /* Too many arguments. */ Fsignal (Qwrong_number_of_arguments, - Fcons (args_template, Fcons (make_number (nargs), Qnil))); + Fcons (Fcons (make_number (mandatory), + make_number (nonrest)), + Fcons (make_number (nargs), Qnil))); + } + else if (! NILP (args_template)) + /* We should push some arguments on the stack. */ + { + error ("Unknown args template!"); } while (1) @@ -603,7 +629,16 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, { Lisp_Object v1; v1 = TOP; - TOP = CAR (v1); + if (CONSP (v1)) + TOP = XCAR (v1); + else if (NILP (v1)) + TOP = Qnil; + else + { + BEFORE_POTENTIAL_GC (); + wrong_type_argument (Qlistp, v1); + AFTER_POTENTIAL_GC (); + } break; } @@ -629,7 +664,17 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, { Lisp_Object v1; v1 = TOP; - TOP = CDR (v1); + if (CONSP (v1)) + TOP = XCDR (v1); + else if (NILP (v1)) + TOP = Qnil; + else + { + BEFORE_POTENTIAL_GC (); + wrong_type_argument (Qlistp, v1); + AFTER_POTENTIAL_GC (); + } + break; break; } @@ -763,7 +808,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, AFTER_POTENTIAL_GC (); break; - case Bunbind_all: /* Obsolete. */ + case Bunbind_all: /* Obsolete. Never used. */ /* To unbind back to the beginning of this frame. Not used yet, but will be needed for tail-recursion elimination. */ BEFORE_POTENTIAL_GC (); @@ -891,19 +936,19 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, save_excursion_save ()); break; - case Bsave_current_buffer: /* Obsolete. */ + case Bsave_current_buffer: /* Obsolete since ??. */ case Bsave_current_buffer_1: record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ()); break; - case Bsave_window_excursion: /* Obsolete. */ + case Bsave_window_excursion: /* Obsolete since 24.1. */ { - register int count = SPECPDL_INDEX (); + register int count1 = SPECPDL_INDEX (); record_unwind_protect (Fset_window_configuration, Fcurrent_window_configuration (Qnil)); BEFORE_POTENTIAL_GC (); TOP = Fprogn (TOP); - unbind_to (count, TOP); + unbind_to (count1, TOP); AFTER_POTENTIAL_GC (); break; } @@ -913,32 +958,32 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, save_restriction_save ()); break; - case Bcatch: + case Bcatch: /* FIXME: ill-suited for lexbind. */ { Lisp_Object v1; BEFORE_POTENTIAL_GC (); v1 = POP; - TOP = internal_catch (TOP, eval_sub, v1); /* FIXME: lexbind */ + TOP = internal_catch (TOP, eval_sub, v1); AFTER_POTENTIAL_GC (); break; } - case Bunwind_protect: - record_unwind_protect (Fprogn, POP); /* FIXME: lexbind */ + case Bunwind_protect: /* FIXME: avoid closure for lexbind. */ + record_unwind_protect (Fprogn, POP); break; - case Bcondition_case: + case Bcondition_case: /* FIXME: ill-suited for lexbind. */ { Lisp_Object handlers, body; handlers = POP; body = POP; BEFORE_POTENTIAL_GC (); - TOP = internal_lisp_condition_case (TOP, body, handlers); /* FIXME: lexbind */ + TOP = internal_lisp_condition_case (TOP, body, handlers); AFTER_POTENTIAL_GC (); break; } - case Btemp_output_buffer_setup: /* Obsolete. */ + case Btemp_output_buffer_setup: /* Obsolete since 24.1. */ BEFORE_POTENTIAL_GC (); CHECK_STRING (TOP); temp_output_buffer_setup (SSDATA (TOP)); @@ -946,7 +991,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, TOP = Vstandard_output; break; - case Btemp_output_buffer_show: /* Obsolete. */ + case Btemp_output_buffer_show: /* Obsolete since 24.1. */ { Lisp_Object v1; BEFORE_POTENTIAL_GC (); @@ -966,13 +1011,13 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, v1 = POP; v2 = TOP; CHECK_NUMBER (v2); - AFTER_POTENTIAL_GC (); op = XINT (v2); immediate_quit = 1; while (--op >= 0 && CONSP (v1)) v1 = XCDR (v1); immediate_quit = 0; TOP = CAR (v1); + AFTER_POTENTIAL_GC (); break; } @@ -1380,7 +1425,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, { Lisp_Object v1; BEFORE_POTENTIAL_GC (); - XSETFASTINT (v1, (int) current_column ()); /* iftc */ + XSETFASTINT (v1, current_column ()); AFTER_POTENTIAL_GC (); PUSH (v1); break; @@ -1418,7 +1463,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, AFTER_POTENTIAL_GC (); break; - case Binteractive_p: /* Obsolete. */ + case Binteractive_p: /* Obsolete since 24.1. */ PUSH (Finteractive_p ()); break; @@ -1468,7 +1513,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, CHECK_CHARACTER (TOP); AFTER_POTENTIAL_GC (); c = XFASTINT (TOP); - if (NILP (current_buffer->enable_multibyte_characters)) + if (NILP (BVAR (current_buffer, enable_multibyte_characters))) MAKE_CHAR_MULTIBYTE (c); XSETFASTINT (TOP, syntax_code_spec[(int) SYNTAX (c)]); } @@ -1707,8 +1752,13 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, break; #endif + case 0: + /* Actually this is Bstack_ref with offset 0, but we use Bdup + for that instead. */ + /* case Bstack_ref: */ + abort (); + /* Handy byte-codes for lexical binding. */ - /* case Bstack_ref: */ /* Use `dup' instead. */ case Bstack_ref+1: case Bstack_ref+2: case Bstack_ref+3: @@ -1731,8 +1781,8 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, PUSH (*ptr); break; } - /* stack-set-0 = discard; stack-set-1 = discard-1-preserve-tos. */ case Bstack_set: + /* stack-set-0 = discard; stack-set-1 = discard-1-preserve-tos. */ { Lisp_Object *ptr = top - (FETCH); *ptr = POP; @@ -1790,8 +1840,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, void syms_of_bytecode (void) { - Qbytecode = intern_c_string ("byte-code"); - staticpro (&Qbytecode); + DEFSYM (Qbytecode, "byte-code"); defsubr (&Sbyte_code); @@ -1813,8 +1862,7 @@ integer, it is incremented each time that symbol's function is called. */); byte_metering_on = 0; Vbyte_code_meter = Fmake_vector (make_number (256), make_number (0)); - Qbyte_code_meter = intern_c_string ("byte-code-meter"); - staticpro (&Qbyte_code_meter); + DEFSYM (Qbyte_code_meter, "byte-code-meter"); { int i = 256; while (i--)