comparison src/bytecode.c @ 380:8626e4521993 r21-2-5

Import from CVS: tag r21-2-5
author cvs
date Mon, 13 Aug 2007 11:07:10 +0200
parents 7df0dd720c89
children 064ab7fed2e0
comparison
equal deleted inserted replaced
379:76b7d63099ad 380:8626e4521993
1 /* Execution of byte code produced by bytecomp.el. 1 /* Execution of byte code produced by bytecomp.el.
2 Implementation of compiled-function objects.
2 Copyright (C) 1992, 1993 Free Software Foundation, Inc. 3 Copyright (C) 1992, 1993 Free Software Foundation, Inc.
3 4
4 This file is part of XEmacs. 5 This file is part of XEmacs.
5 6
6 XEmacs is free software; you can redistribute it and/or modify it 7 XEmacs is free software; you can redistribute it and/or modify it
25 26
26 /* Authorship: 27 /* Authorship:
27 28
28 FSF: long ago. 29 FSF: long ago.
29 30
30 hacked on by jwz@netscape.com 17-jun-91 31 hacked on by jwz@netscape.com 1991-06
31 o added a compile-time switch to turn on simple sanity checking; 32 o added a compile-time switch to turn on simple sanity checking;
32 o put back the obsolete byte-codes for error-detection; 33 o put back the obsolete byte-codes for error-detection;
33 o added a new instruction, unbind_all, which I will use for 34 o added a new instruction, unbind_all, which I will use for
34 tail-recursion elimination; 35 tail-recursion elimination;
35 o made temp_output_buffer_show be called with the right number 36 o made temp_output_buffer_show be called with the right number
39 40
40 by Hallvard: 41 by Hallvard:
41 o added relative jump instructions; 42 o added relative jump instructions;
42 o all conditionals now only do QUIT if they jump. 43 o all conditionals now only do QUIT if they jump.
43 44
44 Ben Wing: some changes for Mule, June 1995. 45 Ben Wing: some changes for Mule, 1995-06.
46
47 Martin Buchholz: performance hacking, 1998-09.
48 See Internals Manual, Evaluation.
45 */ 49 */
46 50
47 #include <config.h> 51 #include <config.h>
48 #include "lisp.h" 52 #include "lisp.h"
53 #include "backtrace.h"
49 #include "buffer.h" 54 #include "buffer.h"
55 #include "bytecode.h"
56 #include "opaque.h"
50 #include "syntax.h" 57 #include "syntax.h"
51 58
52 /* 59 #include <stddef.h>
53 * define BYTE_CODE_SAFE to enable some minor sanity checking (useful for 60 #include <limits.h>
54 * debugging the byte compiler...) Somewhat surprisingly, defining this 61
55 * makes Fbyte_code about 8% slower. 62 EXFUN (Ffetch_bytecode, 1);
56 * 63
57 * define BYTE_CODE_METER to enable generation of a byte-op usage histogram. 64 Lisp_Object Qbyte_code, Qcompiled_functionp, Qinvalid_byte_code;
58 */ 65
59 /* This isn't defined in FSF Emacs and isn't defined in XEmacs v19 */ 66 enum Opcode /* Byte codes */
67 {
68 Bvarref = 010,
69 Bvarset = 020,
70 Bvarbind = 030,
71 Bcall = 040,
72 Bunbind = 050,
73
74 Bnth = 070,
75 Bsymbolp = 071,
76 Bconsp = 072,
77 Bstringp = 073,
78 Blistp = 074,
79 Bold_eq = 075,
80 Bold_memq = 076,
81 Bnot = 077,
82 Bcar = 0100,
83 Bcdr = 0101,
84 Bcons = 0102,
85 Blist1 = 0103,
86 Blist2 = 0104,
87 Blist3 = 0105,
88 Blist4 = 0106,
89 Blength = 0107,
90 Baref = 0110,
91 Baset = 0111,
92 Bsymbol_value = 0112,
93 Bsymbol_function = 0113,
94 Bset = 0114,
95 Bfset = 0115,
96 Bget = 0116,
97 Bsubstring = 0117,
98 Bconcat2 = 0120,
99 Bconcat3 = 0121,
100 Bconcat4 = 0122,
101 Bsub1 = 0123,
102 Badd1 = 0124,
103 Beqlsign = 0125,
104 Bgtr = 0126,
105 Blss = 0127,
106 Bleq = 0130,
107 Bgeq = 0131,
108 Bdiff = 0132,
109 Bnegate = 0133,
110 Bplus = 0134,
111 Bmax = 0135,
112 Bmin = 0136,
113 Bmult = 0137,
114
115 Bpoint = 0140,
116 Beq = 0141, /* was Bmark,
117 but no longer generated as of v18 */
118 Bgoto_char = 0142,
119 Binsert = 0143,
120 Bpoint_max = 0144,
121 Bpoint_min = 0145,
122 Bchar_after = 0146,
123 Bfollowing_char = 0147,
124 Bpreceding_char = 0150,
125 Bcurrent_column = 0151,
126 Bindent_to = 0152,
127 Bequal = 0153, /* was Bscan_buffer,
128 but no longer generated as of v18 */
129 Beolp = 0154,
130 Beobp = 0155,
131 Bbolp = 0156,
132 Bbobp = 0157,
133 Bcurrent_buffer = 0160,
134 Bset_buffer = 0161,
135 Bsave_current_buffer = 0162, /* was Bread_char,
136 but no longer generated as of v19 */
137 Bmemq = 0163, /* was Bset_mark,
138 but no longer generated as of v18 */
139 Binteractive_p = 0164, /* Needed since interactive-p takes
140 unevalled args */
141 Bforward_char = 0165,
142 Bforward_word = 0166,
143 Bskip_chars_forward = 0167,
144 Bskip_chars_backward = 0170,
145 Bforward_line = 0171,
146 Bchar_syntax = 0172,
147 Bbuffer_substring = 0173,
148 Bdelete_region = 0174,
149 Bnarrow_to_region = 0175,
150 Bwiden = 0176,
151 Bend_of_line = 0177,
152
153 Bconstant2 = 0201,
154 Bgoto = 0202,
155 Bgotoifnil = 0203,
156 Bgotoifnonnil = 0204,
157 Bgotoifnilelsepop = 0205,
158 Bgotoifnonnilelsepop = 0206,
159 Breturn = 0207,
160 Bdiscard = 0210,
161 Bdup = 0211,
162
163 Bsave_excursion = 0212,
164 Bsave_window_excursion= 0213,
165 Bsave_restriction = 0214,
166 Bcatch = 0215,
167
168 Bunwind_protect = 0216,
169 Bcondition_case = 0217,
170 Btemp_output_buffer_setup = 0220,
171 Btemp_output_buffer_show = 0221,
172
173 Bunbind_all = 0222,
174
175 Bset_marker = 0223,
176 Bmatch_beginning = 0224,
177 Bmatch_end = 0225,
178 Bupcase = 0226,
179 Bdowncase = 0227,
180
181 Bstring_equal = 0230,
182 Bstring_lessp = 0231,
183 Bold_equal = 0232,
184 Bnthcdr = 0233,
185 Belt = 0234,
186 Bold_member = 0235,
187 Bold_assq = 0236,
188 Bnreverse = 0237,
189 Bsetcar = 0240,
190 Bsetcdr = 0241,
191 Bcar_safe = 0242,
192 Bcdr_safe = 0243,
193 Bnconc = 0244,
194 Bquo = 0245,
195 Brem = 0246,
196 Bnumberp = 0247,
197 Bintegerp = 0250,
198
199 BRgoto = 0252,
200 BRgotoifnil = 0253,
201 BRgotoifnonnil = 0254,
202 BRgotoifnilelsepop = 0255,
203 BRgotoifnonnilelsepop = 0256,
204
205 BlistN = 0257,
206 BconcatN = 0260,
207 BinsertN = 0261,
208 Bmember = 0266, /* new in v20 */
209 Bassq = 0267, /* new in v20 */
210
211 Bconstant = 0300
212 };
213 typedef enum Opcode Opcode;
214 typedef unsigned char Opbyte;
215
216
217 static void invalid_byte_code_error (char *error_message, ...);
218
219 Lisp_Object * execute_rare_opcode (Lisp_Object *stack_ptr,
220 CONST Opbyte *program_ptr,
221 Opcode opcode);
222
223 static Lisp_Object execute_optimized_program (CONST Opbyte *program,
224 int stack_depth,
225 Lisp_Object *constants_data);
226
227 extern Lisp_Object Qand_rest, Qand_optional;
228
229 /* Define ERROR_CHECK_BYTE_CODE to enable some minor sanity checking.
230 Useful for debugging the byte compiler. */
60 #ifdef DEBUG_XEMACS 231 #ifdef DEBUG_XEMACS
61 #define BYTE_CODE_SAFE 232 #define ERROR_CHECK_BYTE_CODE
62 #endif 233 #endif
234
235 /* Define BYTE_CODE_METER to enable generation of a byte-op usage histogram.
236 This isn't defined in FSF Emacs and isn't defined in XEmacs v19. */
63 /* #define BYTE_CODE_METER */ 237 /* #define BYTE_CODE_METER */
64 238
65 239
66 #ifdef BYTE_CODE_METER 240 #ifdef BYTE_CODE_METER
67 241
71 #define METER_2(code1, code2) \ 245 #define METER_2(code1, code2) \
72 XINT (XVECTOR_DATA (XVECTOR_DATA (Vbyte_code_meter)[(code1)])[(code2)]) 246 XINT (XVECTOR_DATA (XVECTOR_DATA (Vbyte_code_meter)[(code1)])[(code2)])
73 247
74 #define METER_1(code) METER_2 (0, (code)) 248 #define METER_1(code) METER_2 (0, (code))
75 249
76 #define METER_CODE(last_code, this_code) \ 250 #define METER_CODE(last_code, this_code) do { \
77 { \ 251 if (byte_metering_on) \
78 if (byte_metering_on) \ 252 { \
79 { \ 253 if (METER_1 (this_code) != ((1<<VALBITS)-1)) \
80 if (METER_1 (this_code) != ((1<<VALBITS)-1)) \ 254 METER_1 (this_code)++; \
81 METER_1 (this_code)++; \ 255 if (last_code \
82 if (last_code \ 256 && METER_2 (last_code, this_code) != ((1<<VALBITS)-1)) \
83 && METER_2 (last_code, this_code) != ((1<<VALBITS)-1))\ 257 METER_2 (last_code, this_code)++; \
84 METER_2 (last_code, this_code)++; \ 258 } \
85 } \ 259 } while (0)
86 } 260
87 261 #endif /* BYTE_CODE_METER */
88 #endif /* no BYTE_CODE_METER */ 262
89 263
90 264 static Lisp_Object
91 Lisp_Object Qbyte_code; 265 bytecode_negate (Lisp_Object obj)
92 266 {
93 /* Byte codes: */ 267 retry:
94 268
95 #define Bvarref 010 269 #ifdef LISP_FLOAT_TYPE
96 #define Bvarset 020 270 if (FLOATP (obj)) return make_float (- XFLOAT_DATA (obj));
97 #define Bvarbind 030 271 #endif
98 #define Bcall 040 272 if (CHARP (obj)) return make_int (- ((int) XCHAR (obj)));
99 #define Bunbind 050 273 if (MARKERP (obj)) return make_int (- ((int) marker_position (obj)));
100 274 if (INTP (obj)) return make_int (- XINT (obj));
101 #define Bnth 070 275
102 #define Bsymbolp 071 276 obj = wrong_type_argument (Qnumber_char_or_marker_p, obj);
103 #define Bconsp 072 277 goto retry;
104 #define Bstringp 073 278 }
105 #define Blistp 074 279
106 #define Bold_eq 075 280 static Lisp_Object
107 #define Bold_memq 076 281 bytecode_nreverse (Lisp_Object list)
108 #define Bnot 077 282 {
109 #define Bcar 0100 283 REGISTER Lisp_Object prev = Qnil;
110 #define Bcdr 0101 284 REGISTER Lisp_Object tail = list;
111 #define Bcons 0102 285
112 #define Blist1 0103 286 while (!NILP (tail))
113 #define Blist2 0104 287 {
114 #define Blist3 0105 288 REGISTER Lisp_Object next;
115 #define Blist4 0106 289 CHECK_CONS (tail);
116 #define Blength 0107 290 next = XCDR (tail);
117 #define Baref 0110 291 XCDR (tail) = prev;
118 #define Baset 0111 292 prev = tail;
119 #define Bsymbol_value 0112 293 tail = next;
120 #define Bsymbol_function 0113 294 }
121 #define Bset 0114 295 return prev;
122 #define Bfset 0115 296 }
123 #define Bget 0116 297
124 #define Bsubstring 0117 298
125 #define Bconcat2 0120 299 /* We have our own two-argument versions of various arithmetic ops.
126 #define Bconcat3 0121 300 Only two-argument arithmetic operations have their own byte codes. */
127 #define Bconcat4 0122 301 static int
128 #define Bsub1 0123 302 bytecode_arithcompare (Lisp_Object obj1, Lisp_Object obj2)
129 #define Badd1 0124 303 {
130 #define Beqlsign 0125 304 retry:
131 #define Bgtr 0126 305
132 #define Blss 0127 306 #ifdef LISP_FLOAT_TYPE
133 #define Bleq 0130 307 {
134 #define Bgeq 0131 308 int ival1, ival2;
135 #define Bdiff 0132 309
136 #define Bnegate 0133 310 if (INTP (obj1)) ival1 = XINT (obj1);
137 #define Bplus 0134 311 else if (CHARP (obj1)) ival1 = XCHAR (obj1);
138 #define Bmax 0135 312 else if (MARKERP (obj1)) ival1 = marker_position (obj1);
139 #define Bmin 0136 313 else goto arithcompare_float;
140 #define Bmult 0137 314
141 315 if (INTP (obj2)) ival2 = XINT (obj2);
142 #define Bpoint 0140 316 else if (CHARP (obj2)) ival2 = XCHAR (obj2);
143 #define Beq 0141 /* was Bmark, but no longer generated as of v18 */ 317 else if (MARKERP (obj2)) ival2 = marker_position (obj2);
144 #define Bgoto_char 0142 318 else goto arithcompare_float;
145 #define Binsert 0143 319
146 #define Bpoint_max 0144 320 return ival1 < ival2 ? -1 : ival1 > ival2 ? 1 : 0;
147 #define Bpoint_min 0145 321 }
148 #define Bchar_after 0146 322
149 #define Bfollowing_char 0147 323 arithcompare_float:
150 #define Bpreceding_char 0150 324
151 #define Bcurrent_column 0151 325 {
152 #define Bindent_to 0152 326 double dval1, dval2;
153 #define Bequal 0153 /* was Bscan_buffer, but no longer generated as of v18 */ 327
154 #define Beolp 0154 328 if (FLOATP (obj1)) dval1 = XFLOAT_DATA (obj1);
155 #define Beobp 0155 329 else if (INTP (obj1)) dval1 = (double) XINT (obj1);
156 #define Bbolp 0156 330 else if (CHARP (obj1)) dval1 = (double) XCHAR (obj1);
157 #define Bbobp 0157 331 else if (MARKERP (obj1)) dval1 = (double) marker_position (obj1);
158 #define Bcurrent_buffer 0160 332 else
159 #define Bset_buffer 0161 333 {
160 #define Bsave_current_buffer 0162 /* was Bread_char, but no longer 334 obj1 = wrong_type_argument (Qnumber_char_or_marker_p, obj1);
161 generated as of v19 */ 335 goto retry;
162 #define Bmemq 0163 /* was Bset_mark, but no longer generated as of v18 */ 336 }
163 #define Binteractive_p 0164 /* Needed since interactive-p takes unevalled args */ 337
164 338 if (FLOATP (obj2)) dval2 = XFLOAT_DATA (obj2);
165 #define Bforward_char 0165 339 else if (INTP (obj2)) dval2 = (double) XINT (obj2);
166 #define Bforward_word 0166 340 else if (CHARP (obj2)) dval2 = (double) XCHAR (obj2);
167 #define Bskip_chars_forward 0167 341 else if (MARKERP (obj2)) dval2 = (double) marker_position (obj2);
168 #define Bskip_chars_backward 0170 342 else
169 #define Bforward_line 0171 343 {
170 #define Bchar_syntax 0172 344 obj2 = wrong_type_argument (Qnumber_char_or_marker_p, obj2);
171 #define Bbuffer_substring 0173 345 goto retry;
172 #define Bdelete_region 0174 346 }
173 #define Bnarrow_to_region 0175 347
174 #define Bwiden 0176 348 return dval1 < dval2 ? -1 : dval1 > dval2 ? 1 : 0;
175 #define Bend_of_line 0177 349 }
176 350 #else /* !LISP_FLOAT_TYPE */
177 #define Bconstant2 0201 351 {
178 #define Bgoto 0202 352 int ival1, ival2;
179 #define Bgotoifnil 0203 353
180 #define Bgotoifnonnil 0204 354 if (INTP (obj1)) ival1 = XINT (obj1);
181 #define Bgotoifnilelsepop 0205 355 else if (CHARP (obj1)) ival1 = XCHAR (obj1);
182 #define Bgotoifnonnilelsepop 0206 356 else if (MARKERP (obj1)) ival1 = marker_position (obj1);
183 #define Breturn 0207 357 else
184 #define Bdiscard 0210 358 {
185 #define Bdup 0211 359 obj1 = wrong_type_argument (Qnumber_char_or_marker_p, obj1);
186 360 goto retry;
187 #define Bsave_excursion 0212 361 }
188 #define Bsave_window_excursion 0213 362
189 #define Bsave_restriction 0214 363 if (INTP (obj2)) ival2 = XINT (obj2);
190 #define Bcatch 0215 364 else if (CHARP (obj2)) ival2 = XCHAR (obj2);
191 365 else if (MARKERP (obj2)) ival2 = marker_position (obj2);
192 #define Bunwind_protect 0216 366 else
193 #define Bcondition_case 0217 367 {
194 #define Btemp_output_buffer_setup 0220 368 obj2 = wrong_type_argument (Qnumber_char_or_marker_p, obj2);
195 #define Btemp_output_buffer_show 0221 369 goto retry;
196 370 }
197 #define Bunbind_all 0222 371
198 372 return ival1 < ival2 ? -1 : ival1 > ival2 ? 1 : 0;
199 #define Bset_marker 0223 373 }
200 #define Bmatch_beginning 0224 374 #endif /* !LISP_FLOAT_TYPE */
201 #define Bmatch_end 0225 375 }
202 #define Bupcase 0226 376
203 #define Bdowncase 0227 377 static Lisp_Object
204 378 bytecode_arithop (Lisp_Object obj1, Lisp_Object obj2, Opcode opcode)
205 #define Bstringeqlsign 0230 379 {
206 #define Bstringlss 0231 380 #ifdef LISP_FLOAT_TYPE
207 #define Bold_equal 0232 381 int ival1, ival2;
208 #define Bnthcdr 0233 382 int float_p;
209 #define Belt 0234 383
210 #define Bold_member 0235 384 retry:
211 #define Bold_assq 0236 385
212 #define Bnreverse 0237 386 float_p = 0;
213 #define Bsetcar 0240 387
214 #define Bsetcdr 0241 388 if (INTP (obj1)) ival1 = XINT (obj1);
215 #define Bcar_safe 0242 389 else if (CHARP (obj1)) ival1 = XCHAR (obj1);
216 #define Bcdr_safe 0243 390 else if (MARKERP (obj1)) ival1 = marker_position (obj1);
217 #define Bnconc 0244 391 else if (FLOATP (obj1)) ival1 = 0, float_p = 1;
218 #define Bquo 0245 392 else
219 #define Brem 0246 393 {
220 #define Bnumberp 0247 394 obj1 = wrong_type_argument (Qnumber_char_or_marker_p, obj1);
221 #define Bintegerp 0250 395 goto retry;
222 396 }
223 #define BRgoto 0252 397
224 #define BRgotoifnil 0253 398 if (INTP (obj2)) ival2 = XINT (obj2);
225 #define BRgotoifnonnil 0254 399 else if (CHARP (obj2)) ival2 = XCHAR (obj2);
226 #define BRgotoifnilelsepop 0255 400 else if (MARKERP (obj2)) ival2 = marker_position (obj2);
227 #define BRgotoifnonnilelsepop 0256 401 else if (FLOATP (obj2)) ival2 = 0, float_p = 1;
228 402 else
229 #define BlistN 0257 403 {
230 #define BconcatN 0260 404 obj2 = wrong_type_argument (Qnumber_char_or_marker_p, obj2);
231 #define BinsertN 0261 405 goto retry;
232 #define Bmember 0266 /* new in v20 */ 406 }
233 #define Bassq 0267 /* new in v20 */ 407
234 408 if (!float_p)
235 #define Bconstant 0300 409 {
236 #define CONSTANTLIM 0100 410 switch (opcode)
411 {
412 case Bplus: ival1 += ival2; break;
413 case Bdiff: ival1 -= ival2; break;
414 case Bmult: ival1 *= ival2; break;
415 case Bquo:
416 if (ival2 == 0) Fsignal (Qarith_error, Qnil);
417 ival1 /= ival2;
418 break;
419 case Bmax: if (ival1 < ival2) ival1 = ival2; break;
420 case Bmin: if (ival1 > ival2) ival1 = ival2; break;
421 }
422 return make_int (ival1);
423 }
424 else
425 {
426 double dval1 = FLOATP (obj1) ? XFLOAT_DATA (obj1) : (double) ival1;
427 double dval2 = FLOATP (obj2) ? XFLOAT_DATA (obj2) : (double) ival2;
428 switch (opcode)
429 {
430 case Bplus: dval1 += dval2; break;
431 case Bdiff: dval1 -= dval2; break;
432 case Bmult: dval1 *= dval2; break;
433 case Bquo:
434 if (dval2 == 0) Fsignal (Qarith_error, Qnil);
435 dval1 /= dval2;
436 break;
437 case Bmax: if (dval1 < dval2) dval1 = dval2; break;
438 case Bmin: if (dval1 > dval2) dval1 = dval2; break;
439 }
440 return make_float (dval1);
441 }
442 #else /* !LISP_FLOAT_TYPE */
443 int ival1, ival2;
444
445 retry:
446
447 if (INTP (obj1)) ival1 = XINT (obj1);
448 else if (CHARP (obj1)) ival1 = XCHAR (obj1);
449 else if (MARKERP (obj1)) ival1 = marker_position (obj1);
450 else
451 {
452 obj1 = wrong_type_argument (Qnumber_char_or_marker_p, obj1);
453 goto retry;
454 }
455
456 if (INTP (obj2)) ival2 = XINT (obj2);
457 else if (CHARP (obj2)) ival2 = XCHAR (obj2);
458 else if (MARKERP (obj2)) ival2 = marker_position (obj2);
459 else
460 {
461 obj2 = wrong_type_argument (Qnumber_char_or_marker_p, obj2);
462 goto retry;
463 }
464
465 switch (opcode)
466 {
467 case Bplus: ival1 += ival2; break;
468 case Bdiff: ival1 -= ival2; break;
469 case Bmult: ival1 *= ival2; break;
470 case Bquo:
471 if (ival2 == 0) Fsignal (Qarith_error, Qnil);
472 ival1 /= ival2;
473 break;
474 case Bmax: if (ival1 < ival2) ival1 = ival2; break;
475 case Bmin: if (ival1 > ival2) ival1 = ival2; break;
476 }
477 return make_int (ival1);
478 #endif /* !LISP_FLOAT_TYPE */
479 }
480
481 /* Apply compiled-function object FUN to the NARGS evaluated arguments
482 in ARGS, and return the result of evaluation. */
483 Lisp_Object
484 funcall_compiled_function (Lisp_Object fun, int nargs, Lisp_Object args[])
485 {
486 /* This function can GC */
487 Lisp_Object symbol, tail;
488 int speccount = specpdl_depth();
489 REGISTER int i = 0;
490 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (fun);
491 int optional = 0;
492
493 if (!OPAQUEP (f->instructions))
494 /* Lazily munge the instructions into a more efficient form */
495 optimize_compiled_function (fun);
496
497 /* optimize_compiled_function() guaranteed that f->specpdl_depth is
498 the required space on the specbinding stack for binding the args
499 and local variables of fun. So just reserve it once. */
500 SPECPDL_RESERVE (f->specpdl_depth);
501
502 /* Fmake_byte_code() guaranteed that f->arglist is a valid list
503 containing only non-constant symbols. */
504 LIST_LOOP_3 (symbol, f->arglist, tail)
505 {
506 if (EQ (symbol, Qand_rest))
507 {
508 tail = XCDR (tail);
509 symbol = XCAR (tail);
510 SPECBIND_FAST_UNSAFE (symbol, Flist (nargs - i, &args[i]));
511 goto run_code;
512 }
513 else if (EQ (symbol, Qand_optional))
514 optional = 1;
515 else if (i == nargs && !optional)
516 goto wrong_number_of_arguments;
517 else
518 SPECBIND_FAST_UNSAFE (symbol, i < nargs ? args[i++] : Qnil);
519 }
520
521 if (i < nargs)
522 goto wrong_number_of_arguments;
523
524 run_code:
525
526 {
527 Lisp_Object value =
528 execute_optimized_program ((Opbyte *) XOPAQUE_DATA (f->instructions),
529 f->stack_depth,
530 XVECTOR_DATA (f->constants));
531
532 UNBIND_TO_GCPRO_VARIABLES_ONLY (speccount, value);
533 return value;
534 }
535
536 wrong_number_of_arguments:
537 return Fsignal (Qwrong_number_of_arguments, list2 (fun, make_int (nargs)));
538 }
539
237 540
238 /* Fetch the next byte from the bytecode stream */ 541 /* Read next uint8 from the instruction stream. */
239 542 #define READ_UINT_1 ((unsigned int) (unsigned char) *program_ptr++)
240 #define FETCH (massaged_code[pc++]) 543
241 544 /* Read next uint16 from the instruction stream. */
242 /* Fetch two bytes from the bytecode stream 545 #define READ_UINT_2 \
243 and make a 16-bit number out of them */ 546 (program_ptr += 2, \
244 547 (((unsigned int) (unsigned char) program_ptr[-1]) * 256 + \
245 #define FETCH2 (op = FETCH, op + (FETCH << 8)) 548 ((unsigned int) (unsigned char) program_ptr[-2])))
549
550 /* Read next int8 from the instruction stream. */
551 #define READ_INT_1 ((int) (signed char) *program_ptr++)
552
553 /* Read next int16 from the instruction stream. */
554 #define READ_INT_2 \
555 (program_ptr += 2, \
556 (((int) ( signed char) program_ptr[-1]) * 256 + \
557 ((int) (unsigned char) program_ptr[-2])))
558
559 /* Read next int8 from instruction stream; don't advance program_pointer */
560 #define PEEK_INT_1 ((int) (signed char) program_ptr[0])
561
562 /* Read next int16 from instruction stream; don't advance program_pointer */
563 #define PEEK_INT_2 \
564 ((((int) ( signed char) program_ptr[1]) * 256) | \
565 ((int) (unsigned char) program_ptr[0]))
566
567 /* Do relative jumps from the current location.
568 We only do a QUIT if we jump backwards, for efficiency.
569 No infloops without backward jumps! */
570 #define JUMP_RELATIVE(jump) do { \
571 int JR_jump = (jump); \
572 if (JR_jump < 0) QUIT; \
573 program_ptr += JR_jump; \
574 } while (0)
575
576 #define JUMP JUMP_RELATIVE (PEEK_INT_2)
577 #define JUMPR JUMP_RELATIVE (PEEK_INT_1)
578
579 #define JUMP_NEXT ((void) (program_ptr += 2))
580 #define JUMPR_NEXT ((void) (program_ptr += 1))
246 581
247 /* Push x onto the execution stack. */ 582 /* Push x onto the execution stack. */
248 583 #define PUSH(x) (*++stack_ptr = (x))
249 #define PUSH(x) (*++stackp = (x)) 584
250 585 /* Pop a value off the execution stack. */
251 /* Pop a value off the execution stack. */ 586 #define POP (*stack_ptr--)
252
253 #define POP (*stackp--)
254 587
255 /* Discard n values from the execution stack. */ 588 /* Discard n values from the execution stack. */
256 589 #define DISCARD(n) (stack_ptr -= (n))
257 #define DISCARD(n) (stackp -= (n))
258 590
259 /* Get the value which is at the top of the execution stack, 591 /* Get the value which is at the top of the execution stack,
260 but don't pop it. */ 592 but don't pop it. */
261 593 #define TOP (*stack_ptr)
262 #define TOP (*stackp) 594
263 595 /* The actual interpreter for byte code.
264 DEFUN ("byte-code", Fbyte_code, 3, 3, 0, /* 596 This function has been seriously optimized for performance.
265 Function used internally in byte-compiled code. 597 Don't change the constructs unless you are willing to do
266 The first argument is a string of byte code; the second, a vector of constants; 598 real benchmarking and profiling work -- martin */
267 the third, the maximum stack depth used in this function. 599
268 If the third argument is incorrect, Emacs may crash. 600
269 */ 601 static Lisp_Object
270 (bytestr, vector, maxdepth)) 602 execute_optimized_program (CONST Opbyte *program,
603 int stack_depth,
604 Lisp_Object *constants_data)
271 { 605 {
272 /* This function can GC */ 606 /* This function can GC */
273 struct gcpro gcpro1, gcpro2, gcpro3; 607 REGISTER CONST Opbyte *program_ptr = (Opbyte *) program;
608 REGISTER Lisp_Object *stack_ptr
609 = alloca_array (Lisp_Object, stack_depth + 1);
274 int speccount = specpdl_depth (); 610 int speccount = specpdl_depth ();
611 struct gcpro gcpro1;
612
275 #ifdef BYTE_CODE_METER 613 #ifdef BYTE_CODE_METER
276 int this_op = 0; 614 Opcode this_opcode = 0;
277 int prev_op; 615 Opcode prev_opcode;
278 #endif 616 #endif
279 REGISTER int op; 617
280 int pc; 618 #ifdef ERROR_CHECK_BYTE_CODE
281 Lisp_Object *stack; 619 Lisp_Object *stack_beg = stack_ptr;
282 REGISTER Lisp_Object *stackp; 620 Lisp_Object *stack_end = stack_beg + stack_depth;
283 Lisp_Object *stacke;
284 REGISTER Lisp_Object v1, v2;
285 REGISTER Lisp_Object *vectorp = XVECTOR_DATA (vector);
286 #ifdef BYTE_CODE_SAFE
287 REGISTER int const_length = XVECTOR_LENGTH (vector);
288 #endif 621 #endif
289 REGISTER Emchar *massaged_code; 622
290 int massaged_code_len; 623 /* Initialize all the objects on the stack to Qnil,
291 624 so we can GCPRO the whole stack.
292 CHECK_STRING (bytestr); 625 The first element of the stack is actually a dummy. */
293 if (!VECTORP (vector)) 626 {
294 vector = wrong_type_argument (Qvectorp, vector); 627 int i;
295 CHECK_NATNUM (maxdepth); 628 Lisp_Object *p;
296 629 for (i = stack_depth, p = stack_ptr; i--;)
297 stackp = alloca_array (Lisp_Object, XINT (maxdepth)); 630 *++p = Qnil;
298 memset (stackp, 0, XINT (maxdepth) * sizeof (Lisp_Object)); 631 }
299 GCPRO3 (bytestr, vector, *stackp); 632
300 gcpro3.nvars = XINT (maxdepth); 633 GCPRO1 (stack_ptr[1]);
301 634 gcpro1.nvars = stack_depth;
302 --stackp;
303 stack = stackp;
304 stacke = stackp + XINT (maxdepth);
305
306 /* Initialize the pc-register and convert the string into a fixed-width
307 format for easier processing. */
308 massaged_code = alloca_array (Emchar, 1 + XSTRING_CHAR_LENGTH (bytestr));
309 massaged_code_len =
310 convert_bufbyte_string_into_emchar_string (XSTRING_DATA (bytestr),
311 XSTRING_LENGTH (bytestr),
312 massaged_code);
313 massaged_code[massaged_code_len] = 0;
314 pc = 0;
315 635
316 while (1) 636 while (1)
317 { 637 {
318 #ifdef BYTE_CODE_SAFE 638 REGISTER Opcode opcode = (Opcode) READ_UINT_1;
319 if (stackp > stacke) 639 #ifdef ERROR_CHECK_BYTE_CODE
320 error ("Byte code stack overflow (byte compiler bug), pc %d, depth %ld", 640 if (stack_ptr > stack_end)
321 pc, (long) (stacke - stackp)); 641 invalid_byte_code_error ("byte code stack overflow");
322 if (stackp < stack) 642 if (stack_ptr < stack_beg)
323 error ("Byte code stack underflow (byte compiler bug), pc %d", 643 invalid_byte_code_error ("byte code stack underflow");
324 pc);
325 #endif 644 #endif
326 645
327 #ifdef BYTE_CODE_METER 646 #ifdef BYTE_CODE_METER
328 prev_op = this_op; 647 prev_opcode = this_opcode;
329 this_op = op = FETCH; 648 this_opcode = opcode;
330 METER_CODE (prev_op, op); 649 METER_CODE (prev_opcode, this_opcode);
331 switch (op)
332 #else
333 switch (op = FETCH)
334 #endif 650 #endif
651
652 switch (opcode)
335 { 653 {
336 case Bvarref+6: 654 REGISTER int n;
337 op = FETCH; 655
338 goto varref; 656 default:
339 657 if (opcode >= Bconstant)
340 case Bvarref+7: 658 PUSH (constants_data[opcode - Bconstant]);
341 op = FETCH2;
342 goto varref;
343
344 case Bvarref: case Bvarref+1: case Bvarref+2: case Bvarref+3:
345 case Bvarref+4: case Bvarref+5:
346 op = op - Bvarref;
347 varref:
348 v1 = vectorp[op];
349 if (!SYMBOLP (v1))
350 v2 = Fsymbol_value (v1);
351 else 659 else
660 stack_ptr = execute_rare_opcode (stack_ptr, program_ptr, opcode);
661 break;
662
663 case Bvarref:
664 case Bvarref+1:
665 case Bvarref+2:
666 case Bvarref+3:
667 case Bvarref+4:
668 case Bvarref+5: n = opcode - Bvarref; goto do_varref;
669 case Bvarref+7: n = READ_UINT_2; goto do_varref;
670 case Bvarref+6: n = READ_UINT_1; /* most common */
671 do_varref:
672 {
673 Lisp_Object symbol = constants_data[n];
674 Lisp_Object value = XSYMBOL (symbol)->value;
675 if (SYMBOL_VALUE_MAGIC_P (value))
676 value = Fsymbol_value (symbol);
677 PUSH (value);
678 break;
679 }
680
681 case Bvarset:
682 case Bvarset+1:
683 case Bvarset+2:
684 case Bvarset+3:
685 case Bvarset+4:
686 case Bvarset+5: n = opcode - Bvarset; goto do_varset;
687 case Bvarset+7: n = READ_UINT_2; goto do_varset;
688 case Bvarset+6: n = READ_UINT_1; /* most common */
689 do_varset:
690 {
691 Lisp_Object symbol = constants_data[n];
692 struct Lisp_Symbol *symbol_ptr = XSYMBOL (symbol);
693 Lisp_Object old_value = symbol_ptr->value;
694 Lisp_Object new_value = POP;
695 if (!SYMBOL_VALUE_MAGIC_P (old_value) || UNBOUNDP (old_value))
696 symbol_ptr->value = new_value;
697 else
698 Fset (symbol, new_value);
699 break;
700 }
701
702 case Bvarbind:
703 case Bvarbind+1:
704 case Bvarbind+2:
705 case Bvarbind+3:
706 case Bvarbind+4:
707 case Bvarbind+5: n = opcode - Bvarbind; goto do_varbind;
708 case Bvarbind+7: n = READ_UINT_2; goto do_varbind;
709 case Bvarbind+6: n = READ_UINT_1; /* most common */
710 do_varbind:
711 {
712 Lisp_Object symbol = constants_data[n];
713 struct Lisp_Symbol *symbol_ptr = XSYMBOL (symbol);
714 Lisp_Object old_value = symbol_ptr->value;
715 Lisp_Object new_value = POP;
716 if (!SYMBOL_VALUE_MAGIC_P (old_value) || UNBOUNDP (old_value))
352 { 717 {
353 v2 = XSYMBOL (v1)->value; 718 specpdl_ptr->symbol = symbol;
354 if (SYMBOL_VALUE_MAGIC_P (v2)) 719 specpdl_ptr->old_value = old_value;
355 v2 = Fsymbol_value (v1); 720 specpdl_ptr->func = 0;
721 specpdl_ptr++;
722 specpdl_depth_counter++;
723
724 symbol_ptr->value = new_value;
356 } 725 }
357 PUSH (v2); 726 else
358 break; 727 specbind_magic (symbol, new_value);
359 728 break;
360 case Bvarset+6: 729 }
361 op = FETCH; 730
362 goto varset; 731 case Bcall:
363 732 case Bcall+1:
364 case Bvarset+7: 733 case Bcall+2:
365 op = FETCH2; 734 case Bcall+3:
366 goto varset; 735 case Bcall+4:
367 736 case Bcall+5:
368 case Bvarset: case Bvarset+1: case Bvarset+2: case Bvarset+3:
369 case Bvarset+4: case Bvarset+5:
370 op -= Bvarset;
371 varset:
372 Fset (vectorp[op], POP);
373 break;
374
375 case Bvarbind+6:
376 op = FETCH;
377 goto varbind;
378
379 case Bvarbind+7:
380 op = FETCH2;
381 goto varbind;
382
383 case Bvarbind: case Bvarbind+1: case Bvarbind+2: case Bvarbind+3:
384 case Bvarbind+4: case Bvarbind+5:
385 op -= Bvarbind;
386 varbind:
387 specbind (vectorp[op], POP);
388 break;
389
390 case Bcall+6: 737 case Bcall+6:
391 op = FETCH;
392 goto docall;
393
394 case Bcall+7: 738 case Bcall+7:
395 op = FETCH2; 739 n = (opcode < Bcall+6 ? opcode - Bcall :
396 goto docall; 740 opcode == Bcall+6 ? READ_UINT_1 : READ_UINT_2);
397 741 DISCARD (n);
398 case Bcall: case Bcall+1: case Bcall+2: case Bcall+3:
399 case Bcall+4: case Bcall+5:
400 op -= Bcall;
401 docall:
402 DISCARD (op);
403 #ifdef BYTE_CODE_METER 742 #ifdef BYTE_CODE_METER
404 if (byte_metering_on && SYMBOLP (TOP)) 743 if (byte_metering_on && SYMBOLP (TOP))
405 { 744 {
406 v1 = TOP; 745 Lisp_Object val = Fget (TOP, Qbyte_code_meter, Qnil);
407 v2 = Fget (v1, Qbyte_code_meter, Qnil); 746 if (INTP (val))
408 if (INTP (v2) 747 Fput (TOP, Qbyte_code_meter, make_int (XINT (val) + 1));
409 && XINT (v2) != ((1<<VALBITS)-1))
410 {
411 XSETINT (v2, XINT (v2) + 1);
412 Fput (v1, Qbyte_code_meter, v2);
413 }
414 } 748 }
415 #endif /* BYTE_CODE_METER */ 749 #endif
416 TOP = Ffuncall (op + 1, &TOP); 750 TOP = Ffuncall (n + 1, &TOP);
417 break; 751 break;
418 752
753 case Bunbind:
754 case Bunbind+1:
755 case Bunbind+2:
756 case Bunbind+3:
757 case Bunbind+4:
758 case Bunbind+5:
419 case Bunbind+6: 759 case Bunbind+6:
420 op = FETCH;
421 goto dounbind;
422
423 case Bunbind+7: 760 case Bunbind+7:
424 op = FETCH2; 761 UNBIND_TO (specpdl_depth() -
425 goto dounbind; 762 (opcode < Bunbind+6 ? opcode-Bunbind :
426 763 opcode == Bunbind+6 ? READ_UINT_1 : READ_UINT_2));
427 case Bunbind: case Bunbind+1: case Bunbind+2: case Bunbind+3: 764 break;
428 case Bunbind+4: case Bunbind+5: 765
429 op -= Bunbind; 766 case Bgoto:
430 dounbind: 767 JUMP;
431 unbind_to (specpdl_depth () - op, Qnil); 768 break;
432 break; 769
770 case Bgotoifnil:
771 if (NILP (POP))
772 JUMP;
773 else
774 JUMP_NEXT;
775 break;
776
777 case Bgotoifnonnil:
778 if (!NILP (POP))
779 JUMP;
780 else
781 JUMP_NEXT;
782 break;
783
784 case Bgotoifnilelsepop:
785 if (NILP (TOP))
786 JUMP;
787 else
788 {
789 DISCARD (1);
790 JUMP_NEXT;
791 }
792 break;
793
794 case Bgotoifnonnilelsepop:
795 if (!NILP (TOP))
796 JUMP;
797 else
798 {
799 DISCARD (1);
800 JUMP_NEXT;
801 }
802 break;
803
804
805 case BRgoto:
806 JUMPR;
807 break;
808
809 case BRgotoifnil:
810 if (NILP (POP))
811 JUMPR;
812 else
813 JUMPR_NEXT;
814 break;
815
816 case BRgotoifnonnil:
817 if (!NILP (POP))
818 JUMPR;
819 else
820 JUMPR_NEXT;
821 break;
822
823 case BRgotoifnilelsepop:
824 if (NILP (TOP))
825 JUMPR;
826 else
827 {
828 DISCARD (1);
829 JUMPR_NEXT;
830 }
831 break;
832
833 case BRgotoifnonnilelsepop:
834 if (!NILP (TOP))
835 JUMPR;
836 else
837 {
838 DISCARD (1);
839 JUMPR_NEXT;
840 }
841 break;
842
843 case Breturn:
844 UNGCPRO;
845 #ifdef ERROR_CHECK_BYTE_CODE
846 /* Binds and unbinds are supposed to be compiled balanced. */
847 if (specpdl_depth() != speccount)
848 invalid_byte_code_error ("unbalanced specbinding stack");
849 #endif
850 return TOP;
851
852 case Bdiscard:
853 DISCARD (1);
854 break;
855
856 case Bdup:
857 {
858 Lisp_Object arg = TOP;
859 PUSH (arg);
860 break;
861 }
862
863 case Bconstant2:
864 PUSH (constants_data[READ_UINT_2]);
865 break;
866
867 case Bcar:
868 TOP = CONSP (TOP) ? XCAR (TOP) : Fcar (TOP);
869 break;
870
871 case Bcdr:
872 TOP = CONSP (TOP) ? XCDR (TOP) : Fcdr (TOP);
873 break;
874
433 875
434 case Bunbind_all: 876 case Bunbind_all:
435 /* To unbind back to the beginning of this frame. Not used yet, 877 /* To unbind back to the beginning of this frame. Not used yet,
436 but will be needed for tail-recursion elimination. */ 878 but will be needed for tail-recursion elimination. */
437 unbind_to (speccount, Qnil); 879 unbind_to (speccount, Qnil);
438 break; 880 break;
439 881
440 case Bgoto:
441 QUIT;
442 op = FETCH2; /* pc = FETCH2 loses since FETCH2 contains pc++ */
443 pc = op;
444 break;
445
446 case Bgotoifnil:
447 op = FETCH2;
448 if (NILP (POP))
449 {
450 QUIT;
451 pc = op;
452 }
453 break;
454
455 case Bgotoifnonnil:
456 op = FETCH2;
457 if (!NILP (POP))
458 {
459 QUIT;
460 pc = op;
461 }
462 break;
463
464 case Bgotoifnilelsepop:
465 op = FETCH2;
466 if (NILP (TOP))
467 {
468 QUIT;
469 pc = op;
470 }
471 else DISCARD (1);
472 break;
473
474 case Bgotoifnonnilelsepop:
475 op = FETCH2;
476 if (!NILP (TOP))
477 {
478 QUIT;
479 pc = op;
480 }
481 else DISCARD (1);
482 break;
483
484 case BRgoto:
485 QUIT;
486 pc += massaged_code[pc] - 127;
487 break;
488
489 case BRgotoifnil:
490 if (NILP (POP))
491 {
492 QUIT;
493 pc += massaged_code[pc] - 128;
494 }
495 pc++;
496 break;
497
498 case BRgotoifnonnil:
499 if (!NILP (POP))
500 {
501 QUIT;
502 pc += massaged_code[pc] - 128;
503 }
504 pc++;
505 break;
506
507 case BRgotoifnilelsepop:
508 op = FETCH;
509 if (NILP (TOP))
510 {
511 QUIT;
512 pc += op - 128;
513 }
514 else DISCARD (1);
515 break;
516
517 case BRgotoifnonnilelsepop:
518 op = FETCH;
519 if (!NILP (TOP))
520 {
521 QUIT;
522 pc += op - 128;
523 }
524 else DISCARD (1);
525 break;
526
527 case Breturn:
528 v1 = POP;
529 goto exit;
530
531 case Bdiscard:
532 DISCARD (1);
533 break;
534
535 case Bdup:
536 v1 = TOP;
537 PUSH (v1);
538 break;
539
540 case Bconstant2:
541 PUSH (vectorp[FETCH2]);
542 break;
543
544 case Bsave_excursion:
545 record_unwind_protect (save_excursion_restore,
546 save_excursion_save ());
547 break;
548
549 case Bsave_window_excursion:
550 {
551 int count = specpdl_depth ();
552 record_unwind_protect (save_window_excursion_unwind,
553 Fcurrent_window_configuration (Qnil));
554 TOP = Fprogn (TOP);
555 unbind_to (count, Qnil);
556 break;
557 }
558
559 case Bsave_restriction:
560 record_unwind_protect (save_restriction_restore,
561 save_restriction_save ());
562 break;
563
564 case Bcatch:
565 v1 = POP;
566 TOP = internal_catch (TOP, Feval, v1, 0);
567 break;
568
569 case Bunwind_protect:
570 record_unwind_protect (Fprogn, POP);
571 break;
572
573 case Bcondition_case:
574 v1 = POP; /* handlers */
575 v2 = POP; /* bodyform */
576 TOP = condition_case_3 (v2, TOP, v1);
577 break;
578
579 case Btemp_output_buffer_setup:
580 temp_output_buffer_setup ((char *) XSTRING_DATA (TOP));
581 TOP = Vstandard_output;
582 break;
583
584 case Btemp_output_buffer_show:
585 v1 = POP;
586 temp_output_buffer_show (TOP, Qnil);
587 TOP = v1;
588 /* GAG ME!! */
589 /* pop binding of standard-output */
590 unbind_to (specpdl_depth() - 1, Qnil);
591 break;
592
593 case Bnth: 882 case Bnth:
594 v1 = POP; 883 {
595 v2 = TOP; 884 Lisp_Object arg = POP;
596 /* nth_entry: */ 885 TOP = Fcar (Fnthcdr (TOP, arg));
597 CHECK_NATNUM (v2); 886 break;
598 for (op = XINT (v2); op; op--) 887 }
599 {
600 if (CONSP (v1))
601 v1 = XCDR (v1);
602 else if (NILP (v1))
603 {
604 TOP = Qnil;
605 goto Bnth_done;
606 }
607 else
608 {
609 v1 = wrong_type_argument (Qlistp, v1);
610 op++;
611 }
612 }
613 goto docar;
614 Bnth_done:
615 break;
616 888
617 case Bsymbolp: 889 case Bsymbolp:
618 TOP = SYMBOLP (TOP) ? Qt : Qnil; 890 TOP = SYMBOLP (TOP) ? Qt : Qnil;
619 break; 891 break;
620 892
628 900
629 case Blistp: 901 case Blistp:
630 TOP = LISTP (TOP) ? Qt : Qnil; 902 TOP = LISTP (TOP) ? Qt : Qnil;
631 break; 903 break;
632 904
905 case Bnumberp:
906 TOP = INT_OR_FLOATP (TOP) ? Qt : Qnil;
907 break;
908
909 case Bintegerp:
910 TOP = INTP (TOP) ? Qt : Qnil;
911 break;
912
633 case Beq: 913 case Beq:
634 v1 = POP; 914 {
635 TOP = EQ_WITH_EBOLA_NOTICE (v1, TOP) ? Qt : Qnil; 915 Lisp_Object arg = POP;
636 break; 916 TOP = EQ_WITH_EBOLA_NOTICE (TOP, arg) ? Qt : Qnil;
637 917 break;
638 case Bold_eq: 918 }
639 v1 = POP;
640 TOP = HACKEQ_UNSAFE (v1, TOP) ? Qt : Qnil;
641 break;
642
643 case Bmemq:
644 v1 = POP;
645 TOP = Fmemq (TOP, v1);
646 break;
647
648 case Bold_memq:
649 v1 = POP;
650 TOP = Fold_memq (TOP, v1);
651 break;
652 919
653 case Bnot: 920 case Bnot:
654 TOP = NILP (TOP) ? Qt : Qnil; 921 TOP = NILP (TOP) ? Qt : Qnil;
655 break; 922 break;
656 923
657 case Bcar: 924 case Bcons:
658 v1 = TOP; 925 {
659 docar: 926 Lisp_Object arg = POP;
660 if (CONSP (v1)) TOP = XCAR (v1); 927 TOP = Fcons (TOP, arg);
661 else if (NILP (v1)) TOP = Qnil; 928 break;
929 }
930
931 case Blist1:
932 TOP = Fcons (TOP, Qnil);
933 break;
934
935
936 case BlistN:
937 n = READ_UINT_1;
938 goto do_list;
939
940 case Blist2:
941 case Blist3:
942 case Blist4:
943 /* common case */
944 n = opcode - (Blist1 - 1);
945 do_list:
946 {
947 Lisp_Object list = Qnil;
948 list_loop:
949 list = Fcons (TOP, list);
950 if (--n)
951 {
952 DISCARD (1);
953 goto list_loop;
954 }
955 TOP = list;
956 break;
957 }
958
959
960 case Bconcat2:
961 case Bconcat3:
962 case Bconcat4:
963 n = opcode - (Bconcat2 - 2);
964 goto do_concat;
965
966 case BconcatN:
967 /* common case */
968 n = READ_UINT_1;
969 do_concat:
970 DISCARD (n - 1);
971 TOP = Fconcat (n, &TOP);
972 break;
973
974
975 case Blength:
976 TOP = Flength (TOP);
977 break;
978
979 case Baset:
980 {
981 Lisp_Object arg2 = POP;
982 Lisp_Object arg1 = POP;
983 TOP = Faset (TOP, arg1, arg2);
984 break;
985 }
986
987 case Bsymbol_value:
988 TOP = Fsymbol_value (TOP);
989 break;
990
991 case Bsymbol_function:
992 TOP = Fsymbol_function (TOP);
993 break;
994
995 case Bget:
996 {
997 Lisp_Object arg = POP;
998 TOP = Fget (TOP, arg, Qnil);
999 break;
1000 }
1001
1002 case Bsub1:
1003 TOP = INTP (TOP) ? make_int (XINT (TOP) - 1) : Fsub1 (TOP);
1004 break;
1005
1006 case Badd1:
1007 TOP = INTP (TOP) ? make_int (XINT (TOP) + 1) : Fadd1 (TOP);
1008 break;
1009
1010
1011 case Beqlsign:
1012 {
1013 Lisp_Object arg = POP;
1014 TOP = bytecode_arithcompare (TOP, arg) == 0 ? Qt : Qnil;
1015 break;
1016 }
1017
1018 case Bgtr:
1019 {
1020 Lisp_Object arg = POP;
1021 TOP = bytecode_arithcompare (TOP, arg) > 0 ? Qt : Qnil;
1022 break;
1023 }
1024
1025 case Blss:
1026 {
1027 Lisp_Object arg = POP;
1028 TOP = bytecode_arithcompare (TOP, arg) < 0 ? Qt : Qnil;
1029 break;
1030 }
1031
1032 case Bleq:
1033 {
1034 Lisp_Object arg = POP;
1035 TOP = bytecode_arithcompare (TOP, arg) <= 0 ? Qt : Qnil;
1036 break;
1037 }
1038
1039 case Bgeq:
1040 {
1041 Lisp_Object arg = POP;
1042 TOP = bytecode_arithcompare (TOP, arg) >= 0 ? Qt : Qnil;
1043 break;
1044 }
1045
1046
1047 case Bnegate:
1048 TOP = bytecode_negate (TOP);
1049 break;
1050
1051 case Bnconc:
1052 DISCARD (1);
1053 TOP = bytecode_nconc2 (&TOP);
1054 break;
1055
1056 case Bplus:
1057 {
1058 Lisp_Object arg2 = POP;
1059 Lisp_Object arg1 = TOP;
1060 TOP = INTP (arg1) && INTP (arg2) ?
1061 make_int (XINT (arg1) + XINT (arg2)) :
1062 bytecode_arithop (arg1, arg2, opcode);
1063 break;
1064 }
1065
1066 case Bdiff:
1067 {
1068 Lisp_Object arg2 = POP;
1069 Lisp_Object arg1 = TOP;
1070 TOP = INTP (arg1) && INTP (arg2) ?
1071 make_int (XINT (arg1) - XINT (arg2)) :
1072 bytecode_arithop (arg1, arg2, opcode);
1073 break;
1074 }
1075
1076 case Bmult:
1077 case Bquo:
1078 case Bmax:
1079 case Bmin:
1080 {
1081 Lisp_Object arg = POP;
1082 TOP = bytecode_arithop (TOP, arg, opcode);
1083 break;
1084 }
1085
1086 case Bpoint:
1087 PUSH (make_int (BUF_PT (current_buffer)));
1088 break;
1089
1090 case Binsert:
1091 TOP = Finsert (1, &TOP);
1092 break;
1093
1094 case BinsertN:
1095 n = READ_UINT_1;
1096 DISCARD (n - 1);
1097 TOP = Finsert (n, &TOP);
1098 break;
1099
1100 case Baref:
1101 {
1102 Lisp_Object arg = POP;
1103 TOP = Faref (TOP, arg);
1104 break;
1105 }
1106
1107 case Bmemq:
1108 {
1109 Lisp_Object arg = POP;
1110 TOP = Fmemq (TOP, arg);
1111 break;
1112 }
1113
1114
1115 case Bset:
1116 {
1117 Lisp_Object arg = POP;
1118 TOP = Fset (TOP, arg);
1119 break;
1120 }
1121
1122 case Bequal:
1123 {
1124 Lisp_Object arg = POP;
1125 TOP = Fequal (TOP, arg);
1126 break;
1127 }
1128
1129 case Bnthcdr:
1130 {
1131 Lisp_Object arg = POP;
1132 TOP = Fnthcdr (TOP, arg);
1133 break;
1134 }
1135
1136 case Belt:
1137 {
1138 Lisp_Object arg = POP;
1139 TOP = Felt (TOP, arg);
1140 break;
1141 }
1142
1143 case Bmember:
1144 {
1145 Lisp_Object arg = POP;
1146 TOP = Fmember (TOP, arg);
1147 break;
1148 }
1149
1150 case Bgoto_char:
1151 TOP = Fgoto_char (TOP, Qnil);
1152 break;
1153
1154 case Bcurrent_buffer:
1155 {
1156 Lisp_Object buffer;
1157 XSETBUFFER (buffer, current_buffer);
1158 PUSH (buffer);
1159 break;
1160 }
1161
1162 case Bset_buffer:
1163 TOP = Fset_buffer (TOP);
1164 break;
1165
1166 case Bpoint_max:
1167 PUSH (make_int (BUF_ZV (current_buffer)));
1168 break;
1169
1170 case Bpoint_min:
1171 PUSH (make_int (BUF_BEGV (current_buffer)));
1172 break;
1173
1174 case Bskip_chars_forward:
1175 {
1176 Lisp_Object arg = POP;
1177 TOP = Fskip_chars_forward (TOP, arg, Qnil);
1178 break;
1179 }
1180
1181 case Bassq:
1182 {
1183 Lisp_Object arg = POP;
1184 TOP = Fassq (TOP, arg);
1185 break;
1186 }
1187
1188 case Bsetcar:
1189 {
1190 Lisp_Object arg = POP;
1191 TOP = Fsetcar (TOP, arg);
1192 break;
1193 }
1194
1195 case Bsetcdr:
1196 {
1197 Lisp_Object arg = POP;
1198 TOP = Fsetcdr (TOP, arg);
1199 break;
1200 }
1201
1202 case Bnreverse:
1203 TOP = bytecode_nreverse (TOP);
1204 break;
1205
1206 case Bcar_safe:
1207 TOP = CONSP (TOP) ? XCAR (TOP) : Qnil;
1208 break;
1209
1210 case Bcdr_safe:
1211 TOP = CONSP (TOP) ? XCDR (TOP) : Qnil;
1212 break;
1213
1214 }
1215 }
1216 }
1217
1218 /* It makes a worthwhile performance difference (5%) to shunt
1219 lesser-used opcodes off to a subroutine, to keep the switch in
1220 execute_optimized_program small. If you REALLY care about
1221 performance, you want to keep your heavily executed code away from
1222 rarely executed code, to minimize cache misses.
1223
1224 Don't make this function static, since then the compiler might inline it. */
1225 Lisp_Object *
1226 execute_rare_opcode (Lisp_Object *stack_ptr,
1227 CONST Opbyte *program_ptr,
1228 Opcode opcode)
1229 {
1230 switch (opcode)
1231 {
1232
1233 case Bsave_excursion:
1234 record_unwind_protect (save_excursion_restore,
1235 save_excursion_save ());
1236 break;
1237
1238 case Bsave_window_excursion:
1239 {
1240 int count = specpdl_depth ();
1241 record_unwind_protect (save_window_excursion_unwind,
1242 Fcurrent_window_configuration (Qnil));
1243 TOP = Fprogn (TOP);
1244 unbind_to (count, Qnil);
1245 break;
1246 }
1247
1248 case Bsave_restriction:
1249 record_unwind_protect (save_restriction_restore,
1250 save_restriction_save ());
1251 break;
1252
1253 case Bcatch:
1254 {
1255 Lisp_Object arg = POP;
1256 TOP = internal_catch (TOP, Feval, arg, 0);
1257 break;
1258 }
1259
1260 case Bskip_chars_backward:
1261 {
1262 Lisp_Object arg = POP;
1263 TOP = Fskip_chars_backward (TOP, arg, Qnil);
1264 break;
1265 }
1266
1267 case Bunwind_protect:
1268 record_unwind_protect (Fprogn, POP);
1269 break;
1270
1271 case Bcondition_case:
1272 {
1273 Lisp_Object arg2 = POP; /* handlers */
1274 Lisp_Object arg1 = POP; /* bodyform */
1275 TOP = condition_case_3 (arg1, TOP, arg2);
1276 break;
1277 }
1278
1279 case Bset_marker:
1280 {
1281 Lisp_Object arg2 = POP;
1282 Lisp_Object arg1 = POP;
1283 TOP = Fset_marker (TOP, arg1, arg2);
1284 break;
1285 }
1286
1287 case Brem:
1288 {
1289 Lisp_Object arg = POP;
1290 TOP = Frem (TOP, arg);
1291 break;
1292 }
1293
1294 case Bmatch_beginning:
1295 TOP = Fmatch_beginning (TOP);
1296 break;
1297
1298 case Bmatch_end:
1299 TOP = Fmatch_end (TOP);
1300 break;
1301
1302 case Bupcase:
1303 TOP = Fupcase (TOP, Qnil);
1304 break;
1305
1306 case Bdowncase:
1307 TOP = Fdowncase (TOP, Qnil);
1308 break;
1309
1310 case Bfset:
1311 {
1312 Lisp_Object arg = POP;
1313 TOP = Ffset (TOP, arg);
1314 break;
1315 }
1316
1317 case Bstring_equal:
1318 {
1319 Lisp_Object arg = POP;
1320 TOP = Fstring_equal (TOP, arg);
1321 break;
1322 }
1323
1324 case Bstring_lessp:
1325 {
1326 Lisp_Object arg = POP;
1327 TOP = Fstring_lessp (TOP, arg);
1328 break;
1329 }
1330
1331 case Bsubstring:
1332 {
1333 Lisp_Object arg2 = POP;
1334 Lisp_Object arg1 = POP;
1335 TOP = Fsubstring (TOP, arg1, arg2);
1336 break;
1337 }
1338
1339 case Bcurrent_column:
1340 PUSH (make_int (current_column (current_buffer)));
1341 break;
1342
1343 case Bchar_after:
1344 TOP = Fchar_after (TOP, Qnil);
1345 break;
1346
1347 case Bindent_to:
1348 TOP = Findent_to (TOP, Qnil, Qnil);
1349 break;
1350
1351 case Bwiden:
1352 PUSH (Fwiden (Qnil));
1353 break;
1354
1355 case Bfollowing_char:
1356 PUSH (Ffollowing_char (Qnil));
1357 break;
1358
1359 case Bpreceding_char:
1360 PUSH (Fpreceding_char (Qnil));
1361 break;
1362
1363 case Beolp:
1364 PUSH (Feolp (Qnil));
1365 break;
1366
1367 case Beobp:
1368 PUSH (Feobp (Qnil));
1369 break;
1370
1371 case Bbolp:
1372 PUSH (Fbolp (Qnil));
1373 break;
1374
1375 case Bbobp:
1376 PUSH (Fbobp (Qnil));
1377 break;
1378
1379 case Bsave_current_buffer:
1380 record_unwind_protect (save_current_buffer_restore,
1381 Fcurrent_buffer ());
1382 break;
1383
1384 case Binteractive_p:
1385 PUSH (Finteractive_p ());
1386 break;
1387
1388 case Bforward_char:
1389 TOP = Fforward_char (TOP, Qnil);
1390 break;
1391
1392 case Bforward_word:
1393 TOP = Fforward_word (TOP, Qnil);
1394 break;
1395
1396 case Bforward_line:
1397 TOP = Fforward_line (TOP, Qnil);
1398 break;
1399
1400 case Bchar_syntax:
1401 TOP = Fchar_syntax (TOP, Qnil);
1402 break;
1403
1404 case Bbuffer_substring:
1405 {
1406 Lisp_Object arg = POP;
1407 TOP = Fbuffer_substring (TOP, arg, Qnil);
1408 break;
1409 }
1410
1411 case Bdelete_region:
1412 {
1413 Lisp_Object arg = POP;
1414 TOP = Fdelete_region (TOP, arg, Qnil);
1415 break;
1416 }
1417
1418 case Bnarrow_to_region:
1419 {
1420 Lisp_Object arg = POP;
1421 TOP = Fnarrow_to_region (TOP, arg, Qnil);
1422 break;
1423 }
1424
1425 case Bend_of_line:
1426 TOP = Fend_of_line (TOP, Qnil);
1427 break;
1428
1429 case Btemp_output_buffer_setup:
1430 temp_output_buffer_setup (TOP);
1431 TOP = Vstandard_output;
1432 break;
1433
1434 case Btemp_output_buffer_show:
1435 {
1436 Lisp_Object arg = POP;
1437 temp_output_buffer_show (TOP, Qnil);
1438 TOP = arg;
1439 /* GAG ME!! */
1440 /* pop binding of standard-output */
1441 unbind_to (specpdl_depth() - 1, Qnil);
1442 break;
1443 }
1444
1445 case Bold_eq:
1446 {
1447 Lisp_Object arg = POP;
1448 TOP = HACKEQ_UNSAFE (TOP, arg) ? Qt : Qnil;
1449 break;
1450 }
1451
1452 case Bold_memq:
1453 {
1454 Lisp_Object arg = POP;
1455 TOP = Fold_memq (TOP, arg);
1456 break;
1457 }
1458
1459 case Bold_equal:
1460 {
1461 Lisp_Object arg = POP;
1462 TOP = Fold_equal (TOP, arg);
1463 break;
1464 }
1465
1466 case Bold_member:
1467 {
1468 Lisp_Object arg = POP;
1469 TOP = Fold_member (TOP, arg);
1470 break;
1471 }
1472
1473 case Bold_assq:
1474 {
1475 Lisp_Object arg = POP;
1476 TOP = Fold_assq (TOP, arg);
1477 break;
1478 }
1479
1480 default:
1481 abort();
1482 break;
1483 }
1484 return stack_ptr;
1485 }
1486
1487
1488 static void
1489 invalid_byte_code_error (char *error_message, ...)
1490 {
1491 Lisp_Object obj;
1492 va_list args;
1493 char *buf = alloca_array (char, strlen (error_message) + 128);
1494
1495 sprintf (buf, "%s", error_message);
1496 va_start (args, error_message);
1497 obj = emacs_doprnt_string_va ((CONST Bufbyte *) GETTEXT (buf), Qnil, -1,
1498 args);
1499 va_end (args);
1500
1501 signal_error (Qinvalid_byte_code, list1 (obj));
1502 }
1503
1504 /* Check for valid opcodes. Change this when adding new opcodes. */
1505 static void
1506 check_opcode (Opcode opcode)
1507 {
1508 if ((opcode < Bvarref) ||
1509 (opcode == 0251) ||
1510 (opcode > Bassq && opcode < Bconstant))
1511 invalid_byte_code_error
1512 ("invalid opcode %d in instruction stream", opcode);
1513 }
1514
1515 /* Check that IDX is a valid offset into the `constants' vector */
1516 static void
1517 check_constants_index (int idx, Lisp_Object constants)
1518 {
1519 if (idx < 0 || idx >= XVECTOR_LENGTH (constants))
1520 invalid_byte_code_error
1521 ("reference %d to constants array out of range 0, %d",
1522 idx, XVECTOR_LENGTH (constants) - 1);
1523 }
1524
1525 /* Get next character from Lisp instructions string. */
1526 #define READ_INSTRUCTION_CHAR(lvalue) do { \
1527 (lvalue) = charptr_emchar (ptr); \
1528 INC_CHARPTR (ptr); \
1529 *icounts_ptr++ = program_ptr - program; \
1530 if (lvalue > UCHAR_MAX) \
1531 invalid_byte_code_error \
1532 ("Invalid character %c in byte code string"); \
1533 } while (0)
1534
1535 /* Get opcode from Lisp instructions string. */
1536 #define READ_OPCODE do { \
1537 unsigned int c; \
1538 READ_INSTRUCTION_CHAR (c); \
1539 opcode = (Opcode) c; \
1540 } while (0)
1541
1542 /* Get next operand, a uint8, from Lisp instructions string. */
1543 #define READ_OPERAND_1 do { \
1544 READ_INSTRUCTION_CHAR (arg); \
1545 argsize = 1; \
1546 } while (0)
1547
1548 /* Get next operand, a uint16, from Lisp instructions string. */
1549 #define READ_OPERAND_2 do { \
1550 unsigned int arg1, arg2; \
1551 READ_INSTRUCTION_CHAR (arg1); \
1552 READ_INSTRUCTION_CHAR (arg2); \
1553 arg = arg1 + (arg2 << 8); \
1554 argsize = 2; \
1555 } while (0)
1556
1557 /* Write 1 byte to PTR, incrementing PTR */
1558 #define WRITE_INT8(value, ptr) do { \
1559 *((ptr)++) = (value); \
1560 } while (0)
1561
1562 /* Write 2 bytes to PTR, incrementing PTR */
1563 #define WRITE_INT16(value, ptr) do { \
1564 WRITE_INT8 (((unsigned) (value)) & 0x00ff, (ptr)); \
1565 WRITE_INT8 (((unsigned) (value)) >> 8 , (ptr)); \
1566 } while (0)
1567
1568 /* We've changed our minds about the opcode we've already written. */
1569 #define REWRITE_OPCODE(new_opcode) ((void) (program_ptr[-1] = new_opcode))
1570
1571 /* Encode an op arg within the opcode, or as a 1 or 2-byte operand. */
1572 #define WRITE_NARGS(base_opcode) do { \
1573 if (arg <= 5) \
1574 { \
1575 REWRITE_OPCODE (base_opcode + arg); \
1576 } \
1577 else if (arg <= UCHAR_MAX) \
1578 { \
1579 REWRITE_OPCODE (base_opcode + 6); \
1580 WRITE_INT8 (arg, program_ptr); \
1581 } \
1582 else \
1583 { \
1584 REWRITE_OPCODE (base_opcode + 7); \
1585 WRITE_INT16 (arg, program_ptr); \
1586 } \
1587 } while (0)
1588
1589 /* Encode a constants reference within the opcode, or as a 2-byte operand. */
1590 #define WRITE_CONSTANT do { \
1591 check_constants_index(arg, constants); \
1592 if (arg <= UCHAR_MAX - Bconstant) \
1593 { \
1594 REWRITE_OPCODE (Bconstant + arg); \
1595 } \
1596 else \
1597 { \
1598 REWRITE_OPCODE (Bconstant2); \
1599 WRITE_INT16 (arg, program_ptr); \
1600 } \
1601 } while (0)
1602
1603 #define WRITE_OPCODE WRITE_INT8 (opcode, program_ptr)
1604
1605 /* Compile byte code instructions into free space provided by caller, with
1606 size >= (2 * string_char_length (instructions) + 1) * sizeof (Opbyte).
1607 Returns length of compiled code. */
1608 static void
1609 optimize_byte_code (/* in */
1610 Lisp_Object instructions,
1611 Lisp_Object constants,
1612 /* out */
1613 Opbyte * CONST program,
1614 int * CONST program_length,
1615 int * CONST varbind_count)
1616 {
1617 size_t instructions_length = XSTRING_LENGTH (instructions);
1618 size_t comfy_size = 2 * instructions_length;
1619
1620 int * CONST icounts = alloca_array (int, comfy_size);
1621 int * icounts_ptr = icounts;
1622
1623 /* We maintain a table of jumps in the source code. */
1624 struct jump
1625 {
1626 int from;
1627 int to;
1628 };
1629 struct jump * CONST jumps = alloca_array (struct jump, comfy_size);
1630 struct jump *jumps_ptr = jumps;
1631
1632 Opbyte *program_ptr = program;
1633
1634 CONST Bufbyte *ptr = XSTRING_DATA (instructions);
1635 CONST Bufbyte * CONST end = ptr + instructions_length;
1636
1637 *varbind_count = 0;
1638
1639 while (ptr < end)
1640 {
1641 Opcode opcode;
1642 int arg;
1643 int argsize = 0;
1644 READ_OPCODE;
1645 WRITE_OPCODE;
1646
1647 switch (opcode)
1648 {
1649 Lisp_Object val;
1650
1651 case Bvarref+7: READ_OPERAND_2; goto do_varref;
1652 case Bvarref+6: READ_OPERAND_1; goto do_varref;
1653 case Bvarref: case Bvarref+1: case Bvarref+2:
1654 case Bvarref+3: case Bvarref+4: case Bvarref+5:
1655 arg = opcode - Bvarref;
1656 do_varref:
1657 check_constants_index (arg, constants);
1658 val = XVECTOR_DATA (constants) [arg];
1659 if (!SYMBOLP (val))
1660 invalid_byte_code_error ("variable reference to non-symbol %S", val);
1661 if (EQ (val, Qnil) || EQ (val, Qt) || (SYMBOL_IS_KEYWORD (val)))
1662 invalid_byte_code_error ("variable reference to constant symbol %s",
1663 string_data (XSYMBOL (val)->name));
1664 WRITE_NARGS (Bvarref);
1665 break;
1666
1667 case Bvarset+7: READ_OPERAND_2; goto do_varset;
1668 case Bvarset+6: READ_OPERAND_1; goto do_varset;
1669 case Bvarset: case Bvarset+1: case Bvarset+2:
1670 case Bvarset+3: case Bvarset+4: case Bvarset+5:
1671 arg = opcode - Bvarset;
1672 do_varset:
1673 check_constants_index (arg, constants);
1674 val = XVECTOR_DATA (constants) [arg];
1675 if (!SYMBOLP (val))
1676 invalid_byte_code_error ("attempt to set non-symbol %S", val);
1677 if (EQ (val, Qnil) || EQ (val, Qt))
1678 invalid_byte_code_error ("attempt to set constant symbol %s",
1679 string_data (XSYMBOL (val)->name));
1680 /* Ignore assignments to keywords by converting to Bdiscard.
1681 For backward compatibility only - we'd like to make this an error. */
1682 if (SYMBOL_IS_KEYWORD (val))
1683 REWRITE_OPCODE (Bdiscard);
1684 else
1685 WRITE_NARGS (Bvarset);
1686 break;
1687
1688 case Bvarbind+7: READ_OPERAND_2; goto do_varbind;
1689 case Bvarbind+6: READ_OPERAND_1; goto do_varbind;
1690 case Bvarbind: case Bvarbind+1: case Bvarbind+2:
1691 case Bvarbind+3: case Bvarbind+4: case Bvarbind+5:
1692 arg = opcode - Bvarbind;
1693 do_varbind:
1694 (*varbind_count)++;
1695 check_constants_index (arg, constants);
1696 val = XVECTOR_DATA (constants) [arg];
1697 if (!SYMBOLP (val))
1698 invalid_byte_code_error ("attempt to let-bind non-symbol %S", val);
1699 if (EQ (val, Qnil) || EQ (val, Qt) || (SYMBOL_IS_KEYWORD (val)))
1700 invalid_byte_code_error ("attempt to let-bind constant symbol %s",
1701 string_data (XSYMBOL (val)->name));
1702 WRITE_NARGS (Bvarbind);
1703 break;
1704
1705 case Bcall+7: READ_OPERAND_2; goto do_call;
1706 case Bcall+6: READ_OPERAND_1; goto do_call;
1707 case Bcall: case Bcall+1: case Bcall+2:
1708 case Bcall+3: case Bcall+4: case Bcall+5:
1709 arg = opcode - Bcall;
1710 do_call:
1711 WRITE_NARGS (Bcall);
1712 break;
1713
1714 case Bunbind+7: READ_OPERAND_2; goto do_unbind;
1715 case Bunbind+6: READ_OPERAND_1; goto do_unbind;
1716 case Bunbind: case Bunbind+1: case Bunbind+2:
1717 case Bunbind+3: case Bunbind+4: case Bunbind+5:
1718 arg = opcode - Bunbind;
1719 do_unbind:
1720 WRITE_NARGS (Bunbind);
1721 break;
1722
1723 case Bgoto:
1724 case Bgotoifnil:
1725 case Bgotoifnonnil:
1726 case Bgotoifnilelsepop:
1727 case Bgotoifnonnilelsepop:
1728 READ_OPERAND_2;
1729 /* Make program_ptr-relative */
1730 arg += icounts - (icounts_ptr - argsize);
1731 goto do_jump;
1732
1733 case BRgoto:
1734 case BRgotoifnil:
1735 case BRgotoifnonnil:
1736 case BRgotoifnilelsepop:
1737 case BRgotoifnonnilelsepop:
1738 READ_OPERAND_1;
1739 /* Make program_ptr-relative */
1740 arg -= 127;
1741 do_jump:
1742 /* Record program-relative goto addresses in `jumps' table */
1743 jumps_ptr->from = icounts_ptr - icounts - argsize;
1744 jumps_ptr->to = jumps_ptr->from + arg;
1745 jumps_ptr++;
1746 if (arg >= -1 && arg <= argsize)
1747 invalid_byte_code_error
1748 ("goto instruction is its own target");
1749 if (arg <= SCHAR_MIN ||
1750 arg > SCHAR_MAX)
1751 {
1752 if (argsize == 1)
1753 REWRITE_OPCODE (opcode + Bgoto - BRgoto);
1754 WRITE_INT16 (arg, program_ptr);
1755 }
662 else 1756 else
663 { 1757 {
664 TOP = wrong_type_argument (Qlistp, v1); 1758 if (argsize == 2)
665 goto docar; 1759 REWRITE_OPCODE (opcode + BRgoto - Bgoto);
1760 WRITE_INT8 (arg, program_ptr);
666 } 1761 }
667 break; 1762 break;
668 1763
669 case Bcdr: 1764 case Bconstant2:
670 v1 = TOP; 1765 READ_OPERAND_2;
671 docdr: 1766 WRITE_CONSTANT;
672 if (CONSP (v1)) TOP = XCDR (v1); 1767 break;
673 else if (NILP (v1)) TOP = Qnil; 1768
1769 case BlistN:
1770 case BconcatN:
1771 case BinsertN:
1772 READ_OPERAND_1;
1773 WRITE_INT8 (arg, program_ptr);
1774 break;
1775
1776 default:
1777 if (opcode < Bconstant)
1778 check_opcode (opcode);
674 else 1779 else
675 { 1780 {
676 TOP = wrong_type_argument (Qlistp, v1); 1781 arg = opcode - Bconstant;
677 goto docdr; 1782 WRITE_CONSTANT;
678 } 1783 }
679 break; 1784 break;
680
681 case Bcons:
682 v1 = POP;
683 TOP = Fcons (TOP, v1);
684 break;
685
686 case Blist1:
687 TOP = Fcons (TOP, Qnil);
688 break;
689
690 case Blist2:
691 v1 = POP;
692 TOP = Fcons (TOP, Fcons (v1, Qnil));
693 break;
694
695 case Blist3:
696 DISCARD (2);
697 TOP = Flist (3, &TOP);
698 break;
699
700 case Blist4:
701 DISCARD (3);
702 TOP = Flist (4, &TOP);
703 break;
704
705 case BlistN:
706 op = FETCH;
707 DISCARD (op - 1);
708 TOP = Flist (op, &TOP);
709 break;
710
711 case Blength:
712 TOP = Flength (TOP);
713 break;
714
715 case Baref:
716 v1 = POP;
717 TOP = Faref (TOP, v1);
718 break;
719
720 case Baset:
721 v2 = POP; v1 = POP;
722 TOP = Faset (TOP, v1, v2);
723 break;
724
725 case Bsymbol_value:
726 TOP = Fsymbol_value (TOP);
727 break;
728
729 case Bsymbol_function:
730 TOP = Fsymbol_function (TOP);
731 break;
732
733 case Bset:
734 v1 = POP;
735 TOP = Fset (TOP, v1);
736 break;
737
738 case Bfset:
739 v1 = POP;
740 TOP = Ffset (TOP, v1);
741 break;
742
743 case Bget:
744 v1 = POP;
745 TOP = Fget (TOP, v1, Qnil);
746 break;
747
748 case Bsubstring:
749 v2 = POP; v1 = POP;
750 TOP = Fsubstring (TOP, v1, v2);
751 break;
752
753 case Bconcat2:
754 DISCARD (1);
755 TOP = Fconcat (2, &TOP);
756 break;
757
758 case Bconcat3:
759 DISCARD (2);
760 TOP = Fconcat (3, &TOP);
761 break;
762
763 case Bconcat4:
764 DISCARD (3);
765 TOP = Fconcat (4, &TOP);
766 break;
767
768 case BconcatN:
769 op = FETCH;
770 DISCARD (op - 1);
771 TOP = Fconcat (op, &TOP);
772 break;
773
774 case Bsub1:
775 v1 = TOP;
776 if (INTP (v1))
777 {
778 XSETINT (v1, XINT (v1) - 1);
779 TOP = v1;
780 }
781 else
782 TOP = Fsub1 (v1);
783 break;
784
785 case Badd1:
786 v1 = TOP;
787 if (INTP (v1))
788 {
789 XSETINT (v1, XINT (v1) + 1);
790 TOP = v1;
791 }
792 else
793 TOP = Fadd1 (v1);
794 break;
795
796 case Beqlsign:
797 v2 = POP; v1 = TOP;
798 CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER (v1);
799 CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER (v2);
800 #ifdef LISP_FLOAT_TYPE
801 if (FLOATP (v1) || FLOATP (v2))
802 {
803 double f1 = (FLOATP (v1) ? float_data (XFLOAT (v1)) : XINT (v1));
804 double f2 = (FLOATP (v2) ? float_data (XFLOAT (v2)) : XINT (v2));
805 TOP = (f1 == f2 ? Qt : Qnil);
806 }
807 else
808 #endif /* LISP_FLOAT_TYPE */
809 TOP = (XINT (v1) == XINT (v2) ? Qt : Qnil);
810 break;
811
812 case Bgtr:
813 v1 = POP;
814 TOP = arithcompare (TOP, v1, arith_grtr);
815 break;
816
817 case Blss:
818 v1 = POP;
819 TOP = arithcompare (TOP, v1, arith_less);
820 break;
821
822 case Bleq:
823 v1 = POP;
824 TOP = arithcompare (TOP, v1, arith_less_or_equal);
825 break;
826
827 case Bgeq:
828 v1 = POP;
829 TOP = arithcompare (TOP, v1, arith_grtr_or_equal);
830 break;
831
832 case Bdiff:
833 DISCARD (1);
834 TOP = Fminus (2, &TOP);
835 break;
836
837 case Bnegate:
838 v1 = TOP;
839 if (INTP (v1))
840 {
841 XSETINT (v1, - XINT (v1));
842 TOP = v1;
843 }
844 else
845 TOP = Fminus (1, &TOP);
846 break;
847
848 case Bplus:
849 DISCARD (1);
850 TOP = Fplus (2, &TOP);
851 break;
852
853 case Bmax:
854 DISCARD (1);
855 TOP = Fmax (2, &TOP);
856 break;
857
858 case Bmin:
859 DISCARD (1);
860 TOP = Fmin (2, &TOP);
861 break;
862
863 case Bmult:
864 DISCARD (1);
865 TOP = Ftimes (2, &TOP);
866 break;
867
868 case Bquo:
869 DISCARD (1);
870 TOP = Fquo (2, &TOP);
871 break;
872
873 case Brem:
874 v1 = POP;
875 TOP = Frem (TOP, v1);
876 break;
877
878 case Bpoint:
879 v1 = make_int (BUF_PT (current_buffer));
880 PUSH (v1);
881 break;
882
883 case Bgoto_char:
884 TOP = Fgoto_char (TOP, Qnil);
885 break;
886
887 case Binsert:
888 TOP = Finsert (1, &TOP);
889 break;
890
891 case BinsertN:
892 op = FETCH;
893 DISCARD (op - 1);
894 TOP = Finsert (op, &TOP);
895 break;
896
897 case Bpoint_max:
898 v1 = make_int (BUF_ZV (current_buffer));
899 PUSH (v1);
900 break;
901
902 case Bpoint_min:
903 v1 = make_int (BUF_BEGV (current_buffer));
904 PUSH (v1);
905 break;
906
907 case Bchar_after:
908 TOP = Fchar_after (TOP, Qnil);
909 break;
910
911 case Bfollowing_char:
912 v1 = Ffollowing_char (Qnil);
913 PUSH (v1);
914 break;
915
916 case Bpreceding_char:
917 v1 = Fpreceding_char (Qnil);
918 PUSH (v1);
919 break;
920
921 case Bcurrent_column:
922 v1 = make_int (current_column (current_buffer));
923 PUSH (v1);
924 break;
925
926 case Bindent_to:
927 TOP = Findent_to (TOP, Qnil, Qnil);
928 break;
929
930 case Beolp:
931 PUSH (Feolp (Qnil));
932 break;
933
934 case Beobp:
935 PUSH (Feobp (Qnil));
936 break;
937
938 case Bbolp:
939 PUSH (Fbolp (Qnil));
940 break;
941
942 case Bbobp:
943 PUSH (Fbobp (Qnil));
944 break;
945
946 case Bcurrent_buffer:
947 PUSH (Fcurrent_buffer ());
948 break;
949
950 case Bset_buffer:
951 TOP = Fset_buffer (TOP);
952 break;
953
954 case Bsave_current_buffer:
955 record_unwind_protect (save_current_buffer_restore,
956 Fcurrent_buffer ());
957 break;
958
959 case Binteractive_p:
960 PUSH (Finteractive_p ());
961 break;
962
963 case Bforward_char:
964 TOP = Fforward_char (TOP, Qnil);
965 break;
966
967 case Bforward_word:
968 TOP = Fforward_word (TOP, Qnil);
969 break;
970
971 case Bskip_chars_forward:
972 v1 = POP;
973 TOP = Fskip_chars_forward (TOP, v1, Qnil);
974 break;
975
976 case Bskip_chars_backward:
977 v1 = POP;
978 TOP = Fskip_chars_backward (TOP, v1, Qnil);
979 break;
980
981 case Bforward_line:
982 TOP = Fforward_line (TOP, Qnil);
983 break;
984
985 case Bchar_syntax:
986 #if 0
987 CHECK_CHAR_COERCE_INT (TOP);
988 TOP = make_char (syntax_code_spec
989 [(int) SYNTAX
990 (XCHAR_TABLE
991 (current_buffer->mirror_syntax_table),
992 XCHAR (TOP))]);
993 #endif
994 /*v1 = POP;*/
995 TOP = Fchar_syntax(TOP, Qnil);
996 break;
997
998 case Bbuffer_substring:
999 v1 = POP;
1000 TOP = Fbuffer_substring (TOP, v1, Qnil);
1001 break;
1002
1003 case Bdelete_region:
1004 v1 = POP;
1005 TOP = Fdelete_region (TOP, v1, Qnil);
1006 break;
1007
1008 case Bnarrow_to_region:
1009 v1 = POP;
1010 TOP = Fnarrow_to_region (TOP, v1, Qnil);
1011 break;
1012
1013 case Bwiden:
1014 PUSH (Fwiden (Qnil));
1015 break;
1016
1017 case Bend_of_line:
1018 TOP = Fend_of_line (TOP, Qnil);
1019 break;
1020
1021 case Bset_marker:
1022 v1 = POP;
1023 v2 = POP;
1024 TOP = Fset_marker (TOP, v2, v1);
1025 break;
1026
1027 case Bmatch_beginning:
1028 TOP = Fmatch_beginning (TOP);
1029 break;
1030
1031 case Bmatch_end:
1032 TOP = Fmatch_end (TOP);
1033 break;
1034
1035 case Bupcase:
1036 TOP = Fupcase (TOP, Qnil);
1037 break;
1038
1039 case Bdowncase:
1040 TOP = Fdowncase (TOP, Qnil);
1041 break;
1042
1043 case Bstringeqlsign:
1044 v1 = POP;
1045 TOP = Fstring_equal (TOP, v1);
1046 break;
1047
1048 case Bstringlss:
1049 v1 = POP;
1050 TOP = Fstring_lessp (TOP, v1);
1051 break;
1052
1053 case Bequal:
1054 v1 = POP;
1055 TOP = Fequal (TOP, v1);
1056 break;
1057
1058 case Bold_equal:
1059 v1 = POP;
1060 TOP = Fold_equal (TOP, v1);
1061 break;
1062
1063 case Bnthcdr:
1064 v1 = POP;
1065 v2 = TOP;
1066 CHECK_NATNUM (v2);
1067 for (op = XINT (v2); op; op--)
1068 {
1069 if (CONSP (v1))
1070 v1 = XCDR (v1);
1071 else if (NILP (v1))
1072 break;
1073 else
1074 {
1075 v1 = wrong_type_argument (Qlistp, v1);
1076 op++;
1077 }
1078 }
1079 TOP = v1;
1080 break;
1081
1082 case Belt:
1083 #if 0
1084 /* probably this code is OK, but nth_entry is commented
1085 out above --ben */
1086 /* #### will not work if cons type is an lrecord. */
1087 if (XTYPE (TOP) == Lisp_Type_Cons)
1088 {
1089 /* Exchange args and then do nth. */
1090 v2 = POP;
1091 v1 = TOP;
1092 goto nth_entry;
1093 }
1094 #endif
1095 v1 = POP;
1096 TOP = Felt (TOP, v1);
1097 break;
1098
1099 case Bmember:
1100 v1 = POP;
1101 TOP = Fmember (TOP, v1);
1102 break;
1103
1104 case Bold_member:
1105 v1 = POP;
1106 TOP = Fold_member (TOP, v1);
1107 break;
1108
1109 case Bassq:
1110 v1 = POP;
1111 TOP = Fassq (TOP, v1);
1112 break;
1113
1114 case Bold_assq:
1115 v1 = POP;
1116 TOP = Fold_assq (TOP, v1);
1117 break;
1118
1119 case Bnreverse:
1120 TOP = Fnreverse (TOP);
1121 break;
1122
1123 case Bsetcar:
1124 v1 = POP;
1125 TOP = Fsetcar (TOP, v1);
1126 break;
1127
1128 case Bsetcdr:
1129 v1 = POP;
1130 TOP = Fsetcdr (TOP, v1);
1131 break;
1132
1133 case Bcar_safe:
1134 v1 = TOP;
1135 if (CONSP (v1))
1136 TOP = XCAR (v1);
1137 else
1138 TOP = Qnil;
1139 break;
1140
1141 case Bcdr_safe:
1142 v1 = TOP;
1143 if (CONSP (v1))
1144 TOP = XCDR (v1);
1145 else
1146 TOP = Qnil;
1147 break;
1148
1149 case Bnconc:
1150 DISCARD (1);
1151 TOP = Fnconc (2, &TOP);
1152 break;
1153
1154 case Bnumberp:
1155 TOP = INT_OR_FLOATP (TOP) ? Qt : Qnil;
1156 break;
1157
1158 case Bintegerp:
1159 TOP = INTP (TOP) ? Qt : Qnil;
1160 break;
1161
1162 default:
1163 #ifdef BYTE_CODE_SAFE
1164 if (op < Bconstant)
1165 error ("unknown bytecode %d (byte compiler bug)", op);
1166 if ((op -= Bconstant) >= const_length)
1167 error ("no constant number %d (byte compiler bug)", op);
1168 PUSH (vectorp[op]);
1169 #else
1170 PUSH (vectorp[op - Bconstant]);
1171 #endif
1172 } 1785 }
1173 } 1786 }
1174 1787
1175 exit: 1788 /* Fix up jumps table to refer to NEW offsets. */
1789 {
1790 struct jump *j;
1791 for (j = jumps; j < jumps_ptr; j++)
1792 {
1793 #ifdef ERROR_CHECK_BYTE_CODE
1794 assert (j->from < icounts_ptr - icounts);
1795 assert (j->to < icounts_ptr - icounts);
1796 #endif
1797 j->from = icounts[j->from];
1798 j->to = icounts[j->to];
1799 #ifdef ERROR_CHECK_BYTE_CODE
1800 assert (j->from < program_ptr - program);
1801 assert (j->to < program_ptr - program);
1802 check_opcode ((Opcode) (program[j->from-1]));
1803 #endif
1804 check_opcode ((Opcode) (program[j->to]));
1805 }
1806 }
1807
1808 /* Fixup jumps in byte-code until no more fixups needed */
1809 {
1810 int more_fixups_needed = 1;
1811
1812 while (more_fixups_needed)
1813 {
1814 struct jump *j;
1815 more_fixups_needed = 0;
1816 for (j = jumps; j < jumps_ptr; j++)
1817 {
1818 int from = j->from;
1819 int to = j->to;
1820 int jump = to - from;
1821 Opbyte *p = program + from;
1822 Opcode opcode = (Opcode) p[-1];
1823 if (!more_fixups_needed)
1824 check_opcode ((Opcode) p[jump]);
1825 assert (to >= 0 && program + to < program_ptr);
1826 switch (opcode)
1827 {
1828 case Bgoto:
1829 case Bgotoifnil:
1830 case Bgotoifnonnil:
1831 case Bgotoifnilelsepop:
1832 case Bgotoifnonnilelsepop:
1833 WRITE_INT16 (jump, p);
1834 break;
1835
1836 case BRgoto:
1837 case BRgotoifnil:
1838 case BRgotoifnonnil:
1839 case BRgotoifnilelsepop:
1840 case BRgotoifnonnilelsepop:
1841 if (jump > SCHAR_MIN &&
1842 jump <= SCHAR_MAX)
1843 {
1844 WRITE_INT8 (jump, p);
1845 }
1846 else /* barf */
1847 {
1848 struct jump *jj;
1849 for (jj = jumps; jj < jumps_ptr; jj++)
1850 {
1851 assert (jj->from < program_ptr - program);
1852 assert (jj->to < program_ptr - program);
1853 if (jj->from > from) jj->from++;
1854 if (jj->to > from) jj->to++;
1855 }
1856 p[-1] += Bgoto - BRgoto;
1857 more_fixups_needed = 1;
1858 memmove (p+1, p, program_ptr++ - p);
1859 WRITE_INT16 (jump, p);
1860 }
1861 break;
1862
1863 default:
1864 abort();
1865 break;
1866 }
1867 }
1868 }
1869 }
1870
1871 /* *program_ptr++ = 0; */
1872 *program_length = program_ptr - program;
1873 }
1874
1875 /* Optimize the byte code and store the optimized program, only
1876 understood by bytecode.c, in an opaque object in the
1877 instructions slot of the Compiled_Function object. */
1878 void
1879 optimize_compiled_function (Lisp_Object compiled_function)
1880 {
1881 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (compiled_function);
1882 int program_length;
1883 int varbind_count;
1884 Opbyte *program;
1885
1886 /* If we have not actually read the bytecode string
1887 and constants vector yet, fetch them from the file. */
1888 if (CONSP (f->instructions))
1889 Ffetch_bytecode (compiled_function);
1890
1891 if (STRINGP (f->instructions))
1892 {
1893 /* XSTRING_LENGTH() is more efficient than XSTRING_CHAR_LENGTH(),
1894 which would be slightly more `proper' */
1895 program = alloca_array (Opbyte, 1 + 2 * XSTRING_LENGTH (f->instructions));
1896 optimize_byte_code (f->instructions, f->constants,
1897 program, &program_length, &varbind_count);
1898 f->specpdl_depth = XINT (Flength (f->arglist)) + varbind_count;
1899 f->instructions =
1900 Fpurecopy (make_opaque (program_length * sizeof (Opbyte),
1901 (CONST void *) program));
1902 }
1903
1904 assert (OPAQUEP (f->instructions));
1905 }
1906
1907 /************************************************************************/
1908 /* The compiled-function object type */
1909 /************************************************************************/
1910 static void
1911 print_compiled_function (Lisp_Object obj, Lisp_Object printcharfun,
1912 int escapeflag)
1913 {
1914 /* This function can GC */
1915 Lisp_Compiled_Function *f =
1916 XCOMPILED_FUNCTION (obj); /* GC doesn't relocate */
1917 int docp = f->flags.documentationp;
1918 int intp = f->flags.interactivep;
1919 struct gcpro gcpro1, gcpro2;
1920 char buf[100];
1921 GCPRO2 (obj, printcharfun);
1922
1923 write_c_string (print_readably ? "#[" : "#<compiled-function ", printcharfun);
1924 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK
1925 if (!print_readably)
1926 {
1927 Lisp_Object ann = compiled_function_annotation (f);
1928 if (!NILP (ann))
1929 {
1930 write_c_string ("(from ", printcharfun);
1931 print_internal (ann, printcharfun, 1);
1932 write_c_string (") ", printcharfun);
1933 }
1934 }
1935 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */
1936 /* COMPILED_ARGLIST = 0 */
1937 print_internal (compiled_function_arglist (f), printcharfun, escapeflag);
1938
1939 /* COMPILED_INSTRUCTIONS = 1 */
1940 write_c_string (" ", printcharfun);
1941 {
1942 struct gcpro ngcpro1;
1943 Lisp_Object instructions = compiled_function_instructions (f);
1944 NGCPRO1 (instructions);
1945 if (STRINGP (instructions) && !print_readably)
1946 {
1947 /* We don't usually want to see that junk in the bytecode. */
1948 sprintf (buf, "\"...(%ld)\"",
1949 (long) XSTRING_CHAR_LENGTH (instructions));
1950 write_c_string (buf, printcharfun);
1951 }
1952 else
1953 print_internal (instructions, printcharfun, escapeflag);
1954 NUNGCPRO;
1955 }
1956
1957 /* COMPILED_CONSTANTS = 2 */
1958 write_c_string (" ", printcharfun);
1959 print_internal (compiled_function_constants (f), printcharfun, escapeflag);
1960
1961 /* COMPILED_STACK_DEPTH = 3 */
1962 sprintf (buf, " %d", compiled_function_stack_depth (f));
1963 write_c_string (buf, printcharfun);
1964
1965 /* COMPILED_DOC_STRING = 4 */
1966 if (docp || intp)
1967 {
1968 write_c_string (" ", printcharfun);
1969 print_internal (compiled_function_documentation (f), printcharfun,
1970 escapeflag);
1971 }
1972
1973 /* COMPILED_INTERACTIVE = 5 */
1974 if (intp)
1975 {
1976 write_c_string (" ", printcharfun);
1977 print_internal (compiled_function_interactive (f), printcharfun,
1978 escapeflag);
1979 }
1980
1176 UNGCPRO; 1981 UNGCPRO;
1177 /* Binds and unbinds are supposed to be compiled balanced. */ 1982 write_c_string (print_readably ? "]" : ">", printcharfun);
1178 if (specpdl_depth() != speccount) 1983 }
1179 /* FSF: abort() if BYTE_CODE_SAFE not defined */ 1984
1180 error ("binding stack not balanced (serious byte compiler bug)"); 1985
1181 return v1; 1986 static Lisp_Object
1182 } 1987 mark_compiled_function (Lisp_Object obj, void (*markobj) (Lisp_Object))
1183 1988 {
1989 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (obj);
1990
1991 markobj (f->instructions);
1992 markobj (f->arglist);
1993 markobj (f->doc_and_interactive);
1994 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK
1995 markobj (f->annotated);
1996 #endif
1997 /* tail-recurse on constants */
1998 return f->constants;
1999 }
2000
2001 static int
2002 compiled_function_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
2003 {
2004 Lisp_Compiled_Function *f1 = XCOMPILED_FUNCTION (obj1);
2005 Lisp_Compiled_Function *f2 = XCOMPILED_FUNCTION (obj2);
2006 return
2007 (f1->flags.documentationp == f2->flags.documentationp &&
2008 f1->flags.interactivep == f2->flags.interactivep &&
2009 f1->flags.domainp == f2->flags.domainp && /* I18N3 */
2010 internal_equal (compiled_function_instructions (f1),
2011 compiled_function_instructions (f2), depth + 1) &&
2012 internal_equal (f1->constants, f2->constants, depth + 1) &&
2013 internal_equal (f1->arglist, f2->arglist, depth + 1) &&
2014 internal_equal (f1->doc_and_interactive,
2015 f2->doc_and_interactive, depth + 1));
2016 }
2017
2018 static unsigned long
2019 compiled_function_hash (Lisp_Object obj, int depth)
2020 {
2021 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (obj);
2022 return HASH3 ((f->flags.documentationp << 2) +
2023 (f->flags.interactivep << 1) +
2024 f->flags.domainp,
2025 internal_hash (f->instructions, depth + 1),
2026 internal_hash (f->constants, depth + 1));
2027 }
2028
2029 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("compiled-function", compiled_function,
2030 mark_compiled_function,
2031 print_compiled_function, 0,
2032 compiled_function_equal,
2033 compiled_function_hash,
2034 Lisp_Compiled_Function);
2035
2036 DEFUN ("compiled-function-p", Fcompiled_function_p, 1, 1, 0, /*
2037 Return t if OBJECT is a byte-compiled function object.
2038 */
2039 (object))
2040 {
2041 return COMPILED_FUNCTIONP (object) ? Qt : Qnil;
2042 }
2043
2044 /************************************************************************/
2045 /* compiled-function object accessor functions */
2046 /************************************************************************/
2047
2048 Lisp_Object
2049 compiled_function_arglist (Lisp_Compiled_Function *f)
2050 {
2051 return f->arglist;
2052 }
2053
2054 Lisp_Object
2055 compiled_function_instructions (Lisp_Compiled_Function *f)
2056 {
2057 if (! OPAQUEP (f->instructions))
2058 return f->instructions;
2059
2060 {
2061 /* Invert action performed by optimize_byte_code() */
2062 Lisp_Opaque *opaque = XOPAQUE (f->instructions);
2063
2064 Bufbyte * CONST buffer =
2065 alloca_array (Bufbyte, OPAQUE_SIZE (opaque) * MAX_EMCHAR_LEN);
2066 Bufbyte *bp = buffer;
2067
2068 CONST Opbyte * CONST program = (CONST Opbyte *) OPAQUE_DATA (opaque);
2069 CONST Opbyte *program_ptr = program;
2070 CONST Opbyte * CONST program_end = program_ptr + OPAQUE_SIZE (opaque);
2071
2072 while (program_ptr < program_end)
2073 {
2074 Opcode opcode = (Opcode) READ_UINT_1;
2075 bp += set_charptr_emchar (bp, opcode);
2076 switch (opcode)
2077 {
2078 case Bvarref+7:
2079 case Bvarset+7:
2080 case Bvarbind+7:
2081 case Bcall+7:
2082 case Bunbind+7:
2083 case Bconstant2:
2084 bp += set_charptr_emchar (bp, READ_UINT_1);
2085 bp += set_charptr_emchar (bp, READ_UINT_1);
2086 break;
2087
2088 case Bvarref+6:
2089 case Bvarset+6:
2090 case Bvarbind+6:
2091 case Bcall+6:
2092 case Bunbind+6:
2093 case BlistN:
2094 case BconcatN:
2095 case BinsertN:
2096 bp += set_charptr_emchar (bp, READ_UINT_1);
2097 break;
2098
2099 case Bgoto:
2100 case Bgotoifnil:
2101 case Bgotoifnonnil:
2102 case Bgotoifnilelsepop:
2103 case Bgotoifnonnilelsepop:
2104 {
2105 int jump = READ_INT_2;
2106 Opbyte buf2[2];
2107 Opbyte *buf2p = buf2;
2108 /* Convert back to program-relative address */
2109 WRITE_INT16 (jump + (program_ptr - 2 - program), buf2p);
2110 bp += set_charptr_emchar (bp, buf2[0]);
2111 bp += set_charptr_emchar (bp, buf2[1]);
2112 break;
2113 }
2114
2115 case BRgoto:
2116 case BRgotoifnil:
2117 case BRgotoifnonnil:
2118 case BRgotoifnilelsepop:
2119 case BRgotoifnonnilelsepop:
2120 bp += set_charptr_emchar (bp, READ_INT_1 + 127);
2121 break;
2122
2123 default:
2124 break;
2125 }
2126 }
2127 return make_string (buffer, bp - buffer);
2128 }
2129 }
2130
2131 Lisp_Object
2132 compiled_function_constants (Lisp_Compiled_Function *f)
2133 {
2134 return f->constants;
2135 }
2136
2137 int
2138 compiled_function_stack_depth (Lisp_Compiled_Function *f)
2139 {
2140 return f->stack_depth;
2141 }
2142
2143 /* The compiled_function->doc_and_interactive slot uses the minimal
2144 number of conses, based on compiled_function->flags; it may take
2145 any of the following forms:
2146
2147 doc
2148 interactive
2149 domain
2150 (doc . interactive)
2151 (doc . domain)
2152 (interactive . domain)
2153 (doc . (interactive . domain))
2154 */
2155
2156 /* Caller must check flags.interactivep first */
2157 Lisp_Object
2158 compiled_function_interactive (Lisp_Compiled_Function *f)
2159 {
2160 assert (f->flags.interactivep);
2161 if (f->flags.documentationp && f->flags.domainp)
2162 return XCAR (XCDR (f->doc_and_interactive));
2163 else if (f->flags.documentationp)
2164 return XCDR (f->doc_and_interactive);
2165 else if (f->flags.domainp)
2166 return XCAR (f->doc_and_interactive);
2167 else
2168 return f->doc_and_interactive;
2169 }
2170
2171 /* Caller need not check flags.documentationp first */
2172 Lisp_Object
2173 compiled_function_documentation (Lisp_Compiled_Function *f)
2174 {
2175 if (! f->flags.documentationp)
2176 return Qnil;
2177 else if (f->flags.interactivep && f->flags.domainp)
2178 return XCAR (f->doc_and_interactive);
2179 else if (f->flags.interactivep)
2180 return XCAR (f->doc_and_interactive);
2181 else if (f->flags.domainp)
2182 return XCAR (f->doc_and_interactive);
2183 else
2184 return f->doc_and_interactive;
2185 }
2186
2187 /* Caller need not check flags.domainp first */
2188 Lisp_Object
2189 compiled_function_domain (Lisp_Compiled_Function *f)
2190 {
2191 if (! f->flags.domainp)
2192 return Qnil;
2193 else if (f->flags.documentationp && f->flags.interactivep)
2194 return XCDR (XCDR (f->doc_and_interactive));
2195 else if (f->flags.documentationp)
2196 return XCDR (f->doc_and_interactive);
2197 else if (f->flags.interactivep)
2198 return XCDR (f->doc_and_interactive);
2199 else
2200 return f->doc_and_interactive;
2201 }
2202
2203 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK
2204
2205 Lisp_Object
2206 compiled_function_annotation (Lisp_Compiled_Function *f)
2207 {
2208 return f->annotated;
2209 }
2210
2211 #endif
2212
2213 /* used only by Snarf-documentation; there must be doc already. */
2214 void
2215 set_compiled_function_documentation (Lisp_Compiled_Function *f,
2216 Lisp_Object new_doc)
2217 {
2218 assert (f->flags.documentationp);
2219 assert (INTP (new_doc) || STRINGP (new_doc));
2220
2221 if (f->flags.interactivep && f->flags.domainp)
2222 XCAR (f->doc_and_interactive) = new_doc;
2223 else if (f->flags.interactivep)
2224 XCAR (f->doc_and_interactive) = new_doc;
2225 else if (f->flags.domainp)
2226 XCAR (f->doc_and_interactive) = new_doc;
2227 else
2228 f->doc_and_interactive = new_doc;
2229 }
2230
2231
2232 DEFUN ("compiled-function-arglist", Fcompiled_function_arglist, 1, 1, 0, /*
2233 Return the argument list of the compiled-function object FUNCTION.
2234 */
2235 (function))
2236 {
2237 CHECK_COMPILED_FUNCTION (function);
2238 return compiled_function_arglist (XCOMPILED_FUNCTION (function));
2239 }
2240
2241 DEFUN ("compiled-function-instructions", Fcompiled_function_instructions, 1, 1, 0, /*
2242 Return the byte-opcode string of the compiled-function object FUNCTION.
2243 */
2244 (function))
2245 {
2246 CHECK_COMPILED_FUNCTION (function);
2247 return compiled_function_instructions (XCOMPILED_FUNCTION (function));
2248 }
2249
2250 DEFUN ("compiled-function-constants", Fcompiled_function_constants, 1, 1, 0, /*
2251 Return the constants vector of the compiled-function object FUNCTION.
2252 */
2253 (function))
2254 {
2255 CHECK_COMPILED_FUNCTION (function);
2256 return compiled_function_constants (XCOMPILED_FUNCTION (function));
2257 }
2258
2259 DEFUN ("compiled-function-stack-depth", Fcompiled_function_stack_depth, 1, 1, 0, /*
2260 Return the max stack depth of the compiled-function object FUNCTION.
2261 */
2262 (function))
2263 {
2264 CHECK_COMPILED_FUNCTION (function);
2265 return make_int (compiled_function_stack_depth (XCOMPILED_FUNCTION (function)));
2266 }
2267
2268 DEFUN ("compiled-function-doc-string", Fcompiled_function_doc_string, 1, 1, 0, /*
2269 Return the doc string of the compiled-function object FUNCTION, if available.
2270 Functions that had their doc strings snarfed into the DOC file will have
2271 an integer returned instead of a string.
2272 */
2273 (function))
2274 {
2275 CHECK_COMPILED_FUNCTION (function);
2276 return compiled_function_documentation (XCOMPILED_FUNCTION (function));
2277 }
2278
2279 DEFUN ("compiled-function-interactive", Fcompiled_function_interactive, 1, 1, 0, /*
2280 Return the interactive spec of the compiled-function object FUNCTION, or nil.
2281 If non-nil, the return value will be a list whose first element is
2282 `interactive' and whose second element is the interactive spec.
2283 */
2284 (function))
2285 {
2286 CHECK_COMPILED_FUNCTION (function);
2287 return XCOMPILED_FUNCTION (function)->flags.interactivep
2288 ? list2 (Qinteractive,
2289 compiled_function_interactive (XCOMPILED_FUNCTION (function)))
2290 : Qnil;
2291 }
2292
2293 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK
2294
2295 /* Remove the `xx' if you wish to restore this feature */
2296 xxDEFUN ("compiled-function-annotation", Fcompiled_function_annotation, 1, 1, 0, /*
2297 Return the annotation of the compiled-function object FUNCTION, or nil.
2298 The annotation is a piece of information indicating where this
2299 compiled-function object came from. Generally this will be
2300 a symbol naming a function; or a string naming a file, if the
2301 compiled-function object was not defined in a function; or nil,
2302 if the compiled-function object was not created as a result of
2303 a `load'.
2304 */
2305 (function))
2306 {
2307 CHECK_COMPILED_FUNCTION (function);
2308 return compiled_function_annotation (XCOMPILED_FUNCTION (function));
2309 }
2310
2311 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */
2312
2313 DEFUN ("compiled-function-domain", Fcompiled_function_domain, 1, 1, 0, /*
2314 Return the domain of the compiled-function object FUNCTION, or nil.
2315 This is only meaningful if I18N3 was enabled when emacs was compiled.
2316 */
2317 (function))
2318 {
2319 CHECK_COMPILED_FUNCTION (function);
2320 return XCOMPILED_FUNCTION (function)->flags.domainp
2321 ? compiled_function_domain (XCOMPILED_FUNCTION (function))
2322 : Qnil;
2323 }
2324
2325
2326
2327 DEFUN ("fetch-bytecode", Ffetch_bytecode, 1, 1, 0, /*
2328 If the byte code for compiled function FUNCTION is lazy-loaded, fetch it now.
2329 */
2330 (function))
2331 {
2332 Lisp_Compiled_Function *f;
2333 CHECK_COMPILED_FUNCTION (function);
2334 f = XCOMPILED_FUNCTION (function);
2335
2336 if (OPAQUEP (f->instructions) || STRINGP (f->instructions))
2337 return function;
2338
2339 if (CONSP (XCOMPILED_FUNCTION (function)->instructions))
2340 {
2341 Lisp_Object tem = read_doc_string (f->instructions);
2342 if (!CONSP (tem))
2343 signal_simple_error ("Invalid lazy-loaded byte code", tem);
2344 /* v18 or v19 bytecode file. Need to Ebolify. */
2345 if (f->flags.ebolified && VECTORP (XCDR (tem)))
2346 ebolify_bytecode_constants (XCDR (tem));
2347 /* VERY IMPORTANT to purecopy here!!!!!
2348 See load_force_doc_string_unwind. */
2349 /* f->instructions = Fpurecopy (XCAR (tem)); */
2350 f->constants = Fpurecopy (XCDR (tem));
2351 return function;
2352 }
2353 abort ();
2354 return Qnil; /* not reached */
2355 }
2356
2357 DEFUN ("optimize-compiled-function", Foptimize_compiled_function, 1, 1, 0, /*
2358 Convert compiled function FUNCTION into an optimized internal form.
2359 */
2360 (function))
2361 {
2362 Lisp_Compiled_Function *f;
2363 CHECK_COMPILED_FUNCTION (function);
2364 f = XCOMPILED_FUNCTION (function);
2365
2366 if (OPAQUEP (f->instructions)) /* Already optimized? */
2367 return Qnil;
2368
2369 optimize_compiled_function (function);
2370 return Qnil;
2371 }
2372
2373 DEFUN ("byte-code", Fbyte_code, 3, 3, 0, /*
2374 Function used internally in byte-compiled code.
2375 First argument INSTRUCTIONS is a string of byte code.
2376 Second argument CONSTANTS is a vector of constants.
2377 Third argument STACK-DEPTH is the maximum stack depth used in this function.
2378 If STACK-DEPTH is incorrect, Emacs may crash.
2379 */
2380 (instructions, constants, stack_depth))
2381 {
2382 /* This function can GC */
2383 int varbind_count;
2384 int program_length;
2385 Opbyte *program;
2386
2387 CHECK_STRING (instructions);
2388 CHECK_VECTOR (constants);
2389 CHECK_NATNUM (stack_depth);
2390
2391 /* Optimize the `instructions' string, just like when executing a
2392 regular compiled function, but don't save it for later since this is
2393 likely to only be executed once. */
2394 program = alloca_array (Opbyte, 1 + 2 * XSTRING_LENGTH (instructions));
2395 optimize_byte_code (instructions, constants, program,
2396 &program_length, &varbind_count);
2397 SPECPDL_RESERVE (varbind_count);
2398 return execute_optimized_program (program,
2399 XINT (stack_depth),
2400 XVECTOR_DATA (constants));
2401 }
2402
2403
1184 void 2404 void
1185 syms_of_bytecode (void) 2405 syms_of_bytecode (void)
1186 { 2406 {
2407 deferror (&Qinvalid_byte_code, "invalid-byte-code",
2408 "Invalid byte code", Qerror);
1187 defsymbol (&Qbyte_code, "byte-code"); 2409 defsymbol (&Qbyte_code, "byte-code");
2410 defsymbol (&Qcompiled_functionp, "compiled-function-p");
2411
1188 DEFSUBR (Fbyte_code); 2412 DEFSUBR (Fbyte_code);
2413 DEFSUBR (Ffetch_bytecode);
2414 DEFSUBR (Foptimize_compiled_function);
2415
2416 DEFSUBR (Fcompiled_function_p);
2417 DEFSUBR (Fcompiled_function_instructions);
2418 DEFSUBR (Fcompiled_function_constants);
2419 DEFSUBR (Fcompiled_function_stack_depth);
2420 DEFSUBR (Fcompiled_function_arglist);
2421 DEFSUBR (Fcompiled_function_interactive);
2422 DEFSUBR (Fcompiled_function_doc_string);
2423 DEFSUBR (Fcompiled_function_domain);
2424 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK
2425 DEFSUBR (Fcompiled_function_annotation);
2426 #endif
2427
1189 #ifdef BYTE_CODE_METER 2428 #ifdef BYTE_CODE_METER
1190 defsymbol (&Qbyte_code_meter, "byte-code-meter"); 2429 defsymbol (&Qbyte_code_meter, "byte-code-meter");
1191 #endif 2430 #endif
1192 } 2431 }
1193 2432
1195 vars_of_bytecode (void) 2434 vars_of_bytecode (void)
1196 { 2435 {
1197 #ifdef BYTE_CODE_METER 2436 #ifdef BYTE_CODE_METER
1198 2437
1199 DEFVAR_LISP ("byte-code-meter", &Vbyte_code_meter /* 2438 DEFVAR_LISP ("byte-code-meter", &Vbyte_code_meter /*
1200 A vector of vectors which holds a histogram of byte-code usage. 2439 A vector of vectors which holds a histogram of byte code usage.
1201 \(aref (aref byte-code-meter 0) CODE) indicates how many times the byte 2440 \(aref (aref byte-code-meter 0) CODE) indicates how many times the byte
1202 opcode CODE has been executed. 2441 opcode CODE has been executed.
1203 \(aref (aref byte-code-meter CODE1) CODE2), where CODE1 is not 0, 2442 \(aref (aref byte-code-meter CODE1) CODE2), where CODE1 is not 0,
1204 indicates how many times the byte opcodes CODE1 and CODE2 have been 2443 indicates how many times the byte opcodes CODE1 and CODE2 have been
1205 executed in succession. 2444 executed in succession.
1206 */ ); 2445 */ );
1207 DEFVAR_BOOL ("byte-metering-on", &byte_metering_on /* 2446 DEFVAR_BOOL ("byte-metering-on", &byte_metering_on /*
1208 If non-nil, keep profiling information on byte code usage. 2447 If non-nil, keep profiling information on byte code usage.
1209 The variable byte-code-meter indicates how often each byte opcode is used. 2448 The variable `byte-code-meter' indicates how often each byte opcode is used.
1210 If a symbol has a property named `byte-code-meter' whose value is an 2449 If a symbol has a property named `byte-code-meter' whose value is an
1211 integer, it is incremented each time that symbol's function is called. 2450 integer, it is incremented each time that symbol's function is called.
1212 */ ); 2451 */ );
1213 2452
1214 byte_metering_on = 0; 2453 byte_metering_on = 0;
1215 Vbyte_code_meter = make_vector (256, Qzero); 2454 Vbyte_code_meter = make_vector (256, Qzero);
1216 { 2455 {
1217 int i = 256; 2456 int i = 256;
1218 while (i--) 2457 while (i--)
1219 XVECTOR_DATA (Vbyte_code_meter)[i] = 2458 XVECTOR_DATA (Vbyte_code_meter)[i] = make_vector (256, Qzero);
1220 make_vector (256, Qzero);
1221 } 2459 }
1222 #endif 2460 #endif /* BYTE_CODE_METER */
1223 } 2461 }