diff options
| author | Paul Eggert | 2015-11-19 20:09:11 -0800 |
|---|---|---|
| committer | Paul Eggert | 2015-11-19 20:09:59 -0800 |
| commit | aa7dac899804727875cdb8fe267d37adcbe9705a (patch) | |
| tree | 7418cf4365ac5a647fe7d91cc818852671ac770b /src | |
| parent | de67fa4258293e18d8aacd6e0c3298f70dbafe32 (diff) | |
| download | emacs-aa7dac899804727875cdb8fe267d37adcbe9705a.tar.gz emacs-aa7dac899804727875cdb8fe267d37adcbe9705a.zip | |
Simplify push_handler and profile its malloc
* src/lisp.h (PUSH_HANDLER): Remove.
All callers changed to use push_handler directly.
* src/eval.c (internal_condition_case)
(internal_condition_case_1, internal_condition_case_2)
(internal_condition_case_n):
Use same pattern as for other invokers of push_handler.
(push_handler, push_handler_nosignal): Use call-by-value
instead of call-by-reference. All uses changed.
(push_handler): Simplify by rewriting in terms of
push_handler_nosignal.
(push_handler_nosignal): Profile any newly allocated memory.
Diffstat (limited to 'src')
| -rw-r--r-- | src/bytecode.c | 14 | ||||
| -rw-r--r-- | src/emacs-module.c | 4 | ||||
| -rw-r--r-- | src/eval.c | 147 | ||||
| -rw-r--r-- | src/lisp.h | 14 |
4 files changed, 71 insertions, 108 deletions
diff --git a/src/bytecode.c b/src/bytecode.c index 864db1a0bed..464adc633a8 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -1067,17 +1067,13 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1067 | type = CATCHER; | 1067 | type = CATCHER; |
| 1068 | goto pushhandler; | 1068 | goto pushhandler; |
| 1069 | CASE (Bpushconditioncase): /* New in 24.4. */ | 1069 | CASE (Bpushconditioncase): /* New in 24.4. */ |
| 1070 | type = CONDITION_CASE; | ||
| 1071 | pushhandler: | ||
| 1070 | { | 1072 | { |
| 1071 | struct handler *c; | 1073 | Lisp_Object tag = POP; |
| 1072 | Lisp_Object tag; | 1074 | int dest = FETCH2; |
| 1073 | int dest; | ||
| 1074 | 1075 | ||
| 1075 | type = CONDITION_CASE; | 1076 | struct handler *c = push_handler (tag, type); |
| 1076 | pushhandler: | ||
| 1077 | tag = POP; | ||
| 1078 | dest = FETCH2; | ||
| 1079 | |||
| 1080 | PUSH_HANDLER (c, tag, type); | ||
| 1081 | c->bytecode_dest = dest; | 1077 | c->bytecode_dest = dest; |
| 1082 | c->bytecode_top = top; | 1078 | c->bytecode_top = top; |
| 1083 | 1079 | ||
diff --git a/src/emacs-module.c b/src/emacs-module.c index f611c8ba600..e885af5de8f 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c | |||
| @@ -194,8 +194,8 @@ static void module_wrong_type (emacs_env *, Lisp_Object, Lisp_Object); | |||
| 194 | #define MODULE_SETJMP_1(handlertype, handlerfunc, retval, c, dummy) \ | 194 | #define MODULE_SETJMP_1(handlertype, handlerfunc, retval, c, dummy) \ |
| 195 | do { \ | 195 | do { \ |
| 196 | eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return); \ | 196 | eassert (module_non_local_exit_check (env) == emacs_funcall_exit_return); \ |
| 197 | struct handler *c; \ | 197 | struct handler *c = push_handler_nosignal (Qt, handlertype); \ |
| 198 | if (!push_handler_nosignal (&c, Qt, handlertype)) \ | 198 | if (!c) \ |
| 199 | { \ | 199 | { \ |
| 200 | module_out_of_memory (env); \ | 200 | module_out_of_memory (env); \ |
| 201 | return retval; \ | 201 | return retval; \ |
diff --git a/src/eval.c b/src/eval.c index 22ee4d1afd1..023c2ef6aab 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -226,9 +226,8 @@ init_eval (void) | |||
| 226 | { /* Put a dummy catcher at top-level so that handlerlist is never NULL. | 226 | { /* Put a dummy catcher at top-level so that handlerlist is never NULL. |
| 227 | This is important since handlerlist->nextfree holds the freelist | 227 | This is important since handlerlist->nextfree holds the freelist |
| 228 | which would otherwise leak every time we unwind back to top-level. */ | 228 | which would otherwise leak every time we unwind back to top-level. */ |
| 229 | struct handler *c; | ||
| 230 | handlerlist = handlerlist_sentinel.nextfree = &handlerlist_sentinel; | 229 | handlerlist = handlerlist_sentinel.nextfree = &handlerlist_sentinel; |
| 231 | PUSH_HANDLER (c, Qunbound, CATCHER); | 230 | struct handler *c = push_handler (Qunbound, CATCHER); |
| 232 | eassert (c == &handlerlist_sentinel); | 231 | eassert (c == &handlerlist_sentinel); |
| 233 | handlerlist_sentinel.nextfree = NULL; | 232 | handlerlist_sentinel.nextfree = NULL; |
| 234 | handlerlist_sentinel.next = NULL; | 233 | handlerlist_sentinel.next = NULL; |
| @@ -1059,18 +1058,16 @@ usage: (catch TAG BODY...) */) | |||
| 1059 | This is how catches are done from within C code. */ | 1058 | This is how catches are done from within C code. */ |
| 1060 | 1059 | ||
| 1061 | Lisp_Object | 1060 | Lisp_Object |
| 1062 | internal_catch (Lisp_Object tag, Lisp_Object (*func) (Lisp_Object), Lisp_Object arg) | 1061 | internal_catch (Lisp_Object tag, |
| 1062 | Lisp_Object (*func) (Lisp_Object), Lisp_Object arg) | ||
| 1063 | { | 1063 | { |
| 1064 | /* This structure is made part of the chain `catchlist'. */ | 1064 | /* This structure is made part of the chain `catchlist'. */ |
| 1065 | struct handler *c; | 1065 | struct handler *c = push_handler (tag, CATCHER); |
| 1066 | |||
| 1067 | /* Fill in the components of c, and put it on the list. */ | ||
| 1068 | PUSH_HANDLER (c, tag, CATCHER); | ||
| 1069 | 1066 | ||
| 1070 | /* Call FUNC. */ | 1067 | /* Call FUNC. */ |
| 1071 | if (! sys_setjmp (c->jmp)) | 1068 | if (! sys_setjmp (c->jmp)) |
| 1072 | { | 1069 | { |
| 1073 | Lisp_Object val = (*func) (arg); | 1070 | Lisp_Object val = func (arg); |
| 1074 | clobbered_eassert (handlerlist == c); | 1071 | clobbered_eassert (handlerlist == c); |
| 1075 | handlerlist = handlerlist->next; | 1072 | handlerlist = handlerlist->next; |
| 1076 | return val; | 1073 | return val; |
| @@ -1147,7 +1144,7 @@ Both TAG and VALUE are evalled. */ | |||
| 1147 | { | 1144 | { |
| 1148 | if (c->type == CATCHER_ALL) | 1145 | if (c->type == CATCHER_ALL) |
| 1149 | unwind_to_catch (c, Fcons (tag, value)); | 1146 | unwind_to_catch (c, Fcons (tag, value)); |
| 1150 | if (c->type == CATCHER && EQ (c->tag_or_ch, tag)) | 1147 | if (c->type == CATCHER && EQ (c->tag_or_ch, tag)) |
| 1151 | unwind_to_catch (c, value); | 1148 | unwind_to_catch (c, value); |
| 1152 | } | 1149 | } |
| 1153 | xsignal2 (Qno_catch, tag, value); | 1150 | xsignal2 (Qno_catch, tag, value); |
| @@ -1213,7 +1210,6 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform, | |||
| 1213 | Lisp_Object handlers) | 1210 | Lisp_Object handlers) |
| 1214 | { | 1211 | { |
| 1215 | Lisp_Object val; | 1212 | Lisp_Object val; |
| 1216 | struct handler *c; | ||
| 1217 | struct handler *oldhandlerlist = handlerlist; | 1213 | struct handler *oldhandlerlist = handlerlist; |
| 1218 | int clausenb = 0; | 1214 | int clausenb = 0; |
| 1219 | 1215 | ||
| @@ -1248,7 +1244,7 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform, | |||
| 1248 | Lisp_Object condition = XCAR (clause); | 1244 | Lisp_Object condition = XCAR (clause); |
| 1249 | if (!CONSP (condition)) | 1245 | if (!CONSP (condition)) |
| 1250 | condition = Fcons (condition, Qnil); | 1246 | condition = Fcons (condition, Qnil); |
| 1251 | PUSH_HANDLER (c, condition, CONDITION_CASE); | 1247 | struct handler *c = push_handler (condition, CONDITION_CASE); |
| 1252 | if (sys_setjmp (c->jmp)) | 1248 | if (sys_setjmp (c->jmp)) |
| 1253 | { | 1249 | { |
| 1254 | ptrdiff_t count = SPECPDL_INDEX (); | 1250 | ptrdiff_t count = SPECPDL_INDEX (); |
| @@ -1296,46 +1292,45 @@ Lisp_Object | |||
| 1296 | internal_condition_case (Lisp_Object (*bfun) (void), Lisp_Object handlers, | 1292 | internal_condition_case (Lisp_Object (*bfun) (void), Lisp_Object handlers, |
| 1297 | Lisp_Object (*hfun) (Lisp_Object)) | 1293 | Lisp_Object (*hfun) (Lisp_Object)) |
| 1298 | { | 1294 | { |
| 1299 | Lisp_Object val; | 1295 | struct handler *c = push_handler (handlers, CONDITION_CASE); |
| 1300 | struct handler *c; | ||
| 1301 | |||
| 1302 | PUSH_HANDLER (c, handlers, CONDITION_CASE); | ||
| 1303 | if (sys_setjmp (c->jmp)) | 1296 | if (sys_setjmp (c->jmp)) |
| 1304 | { | 1297 | { |
| 1305 | Lisp_Object val = handlerlist->val; | 1298 | Lisp_Object val = handlerlist->val; |
| 1306 | clobbered_eassert (handlerlist == c); | 1299 | clobbered_eassert (handlerlist == c); |
| 1307 | handlerlist = handlerlist->next; | 1300 | handlerlist = handlerlist->next; |
| 1308 | return (*hfun) (val); | 1301 | return hfun (val); |
| 1302 | } | ||
| 1303 | else | ||
| 1304 | { | ||
| 1305 | Lisp_Object val = bfun (); | ||
| 1306 | clobbered_eassert (handlerlist == c); | ||
| 1307 | handlerlist = handlerlist->next; | ||
| 1308 | return val; | ||
| 1309 | } | 1309 | } |
| 1310 | |||
| 1311 | val = (*bfun) (); | ||
| 1312 | clobbered_eassert (handlerlist == c); | ||
| 1313 | handlerlist = handlerlist->next; | ||
| 1314 | return val; | ||
| 1315 | } | 1310 | } |
| 1316 | 1311 | ||
| 1317 | /* Like internal_condition_case but call BFUN with ARG as its argument. */ | 1312 | /* Like internal_condition_case but call BFUN with ARG as its argument. */ |
| 1318 | 1313 | ||
| 1319 | Lisp_Object | 1314 | Lisp_Object |
| 1320 | internal_condition_case_1 (Lisp_Object (*bfun) (Lisp_Object), Lisp_Object arg, | 1315 | internal_condition_case_1 (Lisp_Object (*bfun) (Lisp_Object), Lisp_Object arg, |
| 1321 | Lisp_Object handlers, Lisp_Object (*hfun) (Lisp_Object)) | 1316 | Lisp_Object handlers, |
| 1317 | Lisp_Object (*hfun) (Lisp_Object)) | ||
| 1322 | { | 1318 | { |
| 1323 | Lisp_Object val; | 1319 | struct handler *c = push_handler (handlers, CONDITION_CASE); |
| 1324 | struct handler *c; | ||
| 1325 | |||
| 1326 | PUSH_HANDLER (c, handlers, CONDITION_CASE); | ||
| 1327 | if (sys_setjmp (c->jmp)) | 1320 | if (sys_setjmp (c->jmp)) |
| 1328 | { | 1321 | { |
| 1329 | Lisp_Object val = handlerlist->val; | 1322 | Lisp_Object val = handlerlist->val; |
| 1330 | clobbered_eassert (handlerlist == c); | 1323 | clobbered_eassert (handlerlist == c); |
| 1331 | handlerlist = handlerlist->next; | 1324 | handlerlist = handlerlist->next; |
| 1332 | return (*hfun) (val); | 1325 | return hfun (val); |
| 1326 | } | ||
| 1327 | else | ||
| 1328 | { | ||
| 1329 | Lisp_Object val = bfun (arg); | ||
| 1330 | clobbered_eassert (handlerlist == c); | ||
| 1331 | handlerlist = handlerlist->next; | ||
| 1332 | return val; | ||
| 1333 | } | 1333 | } |
| 1334 | |||
| 1335 | val = (*bfun) (arg); | ||
| 1336 | clobbered_eassert (handlerlist == c); | ||
| 1337 | handlerlist = handlerlist->next; | ||
| 1338 | return val; | ||
| 1339 | } | 1334 | } |
| 1340 | 1335 | ||
| 1341 | /* Like internal_condition_case_1 but call BFUN with ARG1 and ARG2 as | 1336 | /* Like internal_condition_case_1 but call BFUN with ARG1 and ARG2 as |
| @@ -1348,22 +1343,21 @@ internal_condition_case_2 (Lisp_Object (*bfun) (Lisp_Object, Lisp_Object), | |||
| 1348 | Lisp_Object handlers, | 1343 | Lisp_Object handlers, |
| 1349 | Lisp_Object (*hfun) (Lisp_Object)) | 1344 | Lisp_Object (*hfun) (Lisp_Object)) |
| 1350 | { | 1345 | { |
| 1351 | Lisp_Object val; | 1346 | struct handler *c = push_handler (handlers, CONDITION_CASE); |
| 1352 | struct handler *c; | ||
| 1353 | |||
| 1354 | PUSH_HANDLER (c, handlers, CONDITION_CASE); | ||
| 1355 | if (sys_setjmp (c->jmp)) | 1347 | if (sys_setjmp (c->jmp)) |
| 1356 | { | 1348 | { |
| 1357 | Lisp_Object val = handlerlist->val; | 1349 | Lisp_Object val = handlerlist->val; |
| 1358 | clobbered_eassert (handlerlist == c); | 1350 | clobbered_eassert (handlerlist == c); |
| 1359 | handlerlist = handlerlist->next; | 1351 | handlerlist = handlerlist->next; |
| 1360 | return (*hfun) (val); | 1352 | return hfun (val); |
| 1353 | } | ||
| 1354 | else | ||
| 1355 | { | ||
| 1356 | Lisp_Object val = bfun (arg1, arg2); | ||
| 1357 | clobbered_eassert (handlerlist == c); | ||
| 1358 | handlerlist = handlerlist->next; | ||
| 1359 | return val; | ||
| 1361 | } | 1360 | } |
| 1362 | |||
| 1363 | val = (*bfun) (arg1, arg2); | ||
| 1364 | clobbered_eassert (handlerlist == c); | ||
| 1365 | handlerlist = handlerlist->next; | ||
| 1366 | return val; | ||
| 1367 | } | 1361 | } |
| 1368 | 1362 | ||
| 1369 | /* Like internal_condition_case but call BFUN with NARGS as first, | 1363 | /* Like internal_condition_case but call BFUN with NARGS as first, |
| @@ -1378,64 +1372,46 @@ internal_condition_case_n (Lisp_Object (*bfun) (ptrdiff_t, Lisp_Object *), | |||
| 1378 | ptrdiff_t nargs, | 1372 | ptrdiff_t nargs, |
| 1379 | Lisp_Object *args)) | 1373 | Lisp_Object *args)) |
| 1380 | { | 1374 | { |
| 1381 | Lisp_Object val; | 1375 | struct handler *c = push_handler (handlers, CONDITION_CASE); |
| 1382 | struct handler *c; | ||
| 1383 | |||
| 1384 | PUSH_HANDLER (c, handlers, CONDITION_CASE); | ||
| 1385 | if (sys_setjmp (c->jmp)) | 1376 | if (sys_setjmp (c->jmp)) |
| 1386 | { | 1377 | { |
| 1387 | Lisp_Object val = handlerlist->val; | 1378 | Lisp_Object val = handlerlist->val; |
| 1388 | clobbered_eassert (handlerlist == c); | 1379 | clobbered_eassert (handlerlist == c); |
| 1389 | handlerlist = handlerlist->next; | 1380 | handlerlist = handlerlist->next; |
| 1390 | return (*hfun) (val, nargs, args); | 1381 | return hfun (val, nargs, args); |
| 1391 | } | 1382 | } |
| 1392 | |||
| 1393 | val = (*bfun) (nargs, args); | ||
| 1394 | clobbered_eassert (handlerlist == c); | ||
| 1395 | handlerlist = handlerlist->next; | ||
| 1396 | return val; | ||
| 1397 | } | ||
| 1398 | |||
| 1399 | static void init_handler (struct handler *c, Lisp_Object tag_ch_val, | ||
| 1400 | enum handlertype handlertype); | ||
| 1401 | |||
| 1402 | void | ||
| 1403 | push_handler (struct handler **c, Lisp_Object tag_ch_val, | ||
| 1404 | enum handlertype handlertype) | ||
| 1405 | { | ||
| 1406 | if (handlerlist->nextfree) | ||
| 1407 | *c = handlerlist->nextfree; | ||
| 1408 | else | 1383 | else |
| 1409 | { | 1384 | { |
| 1410 | *c = xmalloc (sizeof (struct handler)); | 1385 | Lisp_Object val = bfun (nargs, args); |
| 1411 | (*c)->nextfree = NULL; | 1386 | clobbered_eassert (handlerlist == c); |
| 1412 | handlerlist->nextfree = *c; | 1387 | handlerlist = handlerlist->next; |
| 1388 | return val; | ||
| 1413 | } | 1389 | } |
| 1414 | init_handler (*c, tag_ch_val, handlertype); | ||
| 1415 | } | 1390 | } |
| 1416 | 1391 | ||
| 1417 | bool | 1392 | struct handler * |
| 1418 | push_handler_nosignal (struct handler **c, Lisp_Object tag_ch_val, | 1393 | push_handler (Lisp_Object tag_ch_val, enum handlertype handlertype) |
| 1419 | enum handlertype handlertype) | ||
| 1420 | { | 1394 | { |
| 1421 | if (handlerlist->nextfree) | 1395 | struct handler *c = push_handler_nosignal (tag_ch_val, handlertype); |
| 1422 | *c = handlerlist->nextfree; | 1396 | if (!c) |
| 1423 | else | 1397 | memory_full (sizeof *c); |
| 1424 | { | 1398 | return c; |
| 1425 | struct handler *h = malloc (sizeof (struct handler)); | ||
| 1426 | if (! h) return false; | ||
| 1427 | *c = h; | ||
| 1428 | h->nextfree = NULL; | ||
| 1429 | handlerlist->nextfree = h; | ||
| 1430 | } | ||
| 1431 | init_handler (*c, tag_ch_val, handlertype); | ||
| 1432 | return true; | ||
| 1433 | } | 1399 | } |
| 1434 | 1400 | ||
| 1435 | static void | 1401 | struct handler * |
| 1436 | init_handler (struct handler *c, Lisp_Object tag_ch_val, | 1402 | push_handler_nosignal (Lisp_Object tag_ch_val, enum handlertype handlertype) |
| 1437 | enum handlertype handlertype) | ||
| 1438 | { | 1403 | { |
| 1404 | struct handler *c = handlerlist->nextfree; | ||
| 1405 | if (!c) | ||
| 1406 | { | ||
| 1407 | c = malloc (sizeof *c); | ||
| 1408 | if (!c) | ||
| 1409 | return c; | ||
| 1410 | if (profiler_memory_running) | ||
| 1411 | malloc_probe (sizeof *c); | ||
| 1412 | c->nextfree = NULL; | ||
| 1413 | handlerlist->nextfree = c; | ||
| 1414 | } | ||
| 1439 | c->type = handlertype; | 1415 | c->type = handlertype; |
| 1440 | c->tag_or_ch = tag_ch_val; | 1416 | c->tag_or_ch = tag_ch_val; |
| 1441 | c->val = Qnil; | 1417 | c->val = Qnil; |
| @@ -1446,6 +1422,7 @@ init_handler (struct handler *c, Lisp_Object tag_ch_val, | |||
| 1446 | c->interrupt_input_blocked = interrupt_input_blocked; | 1422 | c->interrupt_input_blocked = interrupt_input_blocked; |
| 1447 | c->byte_stack = byte_stack_list; | 1423 | c->byte_stack = byte_stack_list; |
| 1448 | handlerlist = c; | 1424 | handlerlist = c; |
| 1425 | return c; | ||
| 1449 | } | 1426 | } |
| 1450 | 1427 | ||
| 1451 | 1428 | ||
diff --git a/src/lisp.h b/src/lisp.h index 3b7bb40caa2..71dca7201d0 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3183,18 +3183,6 @@ struct handler | |||
| 3183 | struct byte_stack *byte_stack; | 3183 | struct byte_stack *byte_stack; |
| 3184 | }; | 3184 | }; |
| 3185 | 3185 | ||
| 3186 | /* Fill in the components of c, and put it on the list. */ | ||
| 3187 | #define PUSH_HANDLER(c, tag_ch_val, handlertype) \ | ||
| 3188 | push_handler(&(c), (tag_ch_val), (handlertype)) | ||
| 3189 | |||
| 3190 | extern void push_handler (struct handler **c, Lisp_Object tag_ch_val, | ||
| 3191 | enum handlertype handlertype); | ||
| 3192 | |||
| 3193 | /* Like push_handler, but don't signal if the handler could not be | ||
| 3194 | allocated. Instead return false in that case. */ | ||
| 3195 | extern bool push_handler_nosignal (struct handler **c, Lisp_Object tag_ch_val, | ||
| 3196 | enum handlertype handlertype); | ||
| 3197 | |||
| 3198 | extern Lisp_Object memory_signal_data; | 3186 | extern Lisp_Object memory_signal_data; |
| 3199 | 3187 | ||
| 3200 | /* An address near the bottom of the stack. | 3188 | /* An address near the bottom of the stack. |
| @@ -3880,6 +3868,8 @@ extern Lisp_Object internal_condition_case_2 (Lisp_Object (*) (Lisp_Object, Lisp | |||
| 3880 | extern Lisp_Object internal_condition_case_n | 3868 | extern Lisp_Object internal_condition_case_n |
| 3881 | (Lisp_Object (*) (ptrdiff_t, Lisp_Object *), ptrdiff_t, Lisp_Object *, | 3869 | (Lisp_Object (*) (ptrdiff_t, Lisp_Object *), ptrdiff_t, Lisp_Object *, |
| 3882 | Lisp_Object, Lisp_Object (*) (Lisp_Object, ptrdiff_t, Lisp_Object *)); | 3870 | Lisp_Object, Lisp_Object (*) (Lisp_Object, ptrdiff_t, Lisp_Object *)); |
| 3871 | extern struct handler *push_handler (Lisp_Object, enum handlertype); | ||
| 3872 | extern struct handler *push_handler_nosignal (Lisp_Object, enum handlertype); | ||
| 3883 | extern void specbind (Lisp_Object, Lisp_Object); | 3873 | extern void specbind (Lisp_Object, Lisp_Object); |
| 3884 | extern void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object); | 3874 | extern void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object); |
| 3885 | extern void record_unwind_protect_ptr (void (*) (void *), void *); | 3875 | extern void record_unwind_protect_ptr (void (*) (void *), void *); |