diff options
| author | Dmitry Antipov | 2014-06-08 19:06:03 +0400 |
|---|---|---|
| committer | Dmitry Antipov | 2014-06-08 19:06:03 +0400 |
| commit | 83f1450065c55a3e5dce5db0da737cb7a6a4d60c (patch) | |
| tree | 92d118deaa0a9a24d48aa22353c5c413377267d7 /src | |
| parent | 36cf8493aff99b652b2ad8c9e4d55a18688e8484 (diff) | |
| download | emacs-83f1450065c55a3e5dce5db0da737cb7a6a4d60c.tar.gz emacs-83f1450065c55a3e5dce5db0da737cb7a6a4d60c.zip | |
Change object marking routines to minimize stack usage.
This change moves a few cold paths from mark_object to NO_INLINE
functions and adjusts symbol marking loop. According to GCC 4.8.2
-Wstack-usage, this reduces mark_object's stack usage from 80 to
48 bytes on a 64-bit system. For a long byte-force-recompile runs,
stack usage at the mark phase is reduced up to 28%. Surprisingly,
it also gains up to 3% in speed (with default '-O2 -g3' flags).
* alloc.c (mark_compiled, mark_localized_symbol): New functions,
refactored out from ...
(mark_object): ... adjusted user. Also mark symbols in a tight
inner loop.
(mark_face_cache): Add NO_INLINE.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 15 | ||||
| -rw-r--r-- | src/alloc.c | 83 |
2 files changed, 59 insertions, 39 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 4aada1d5279..2cdaf494aad 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,18 @@ | |||
| 1 | 2014-06-08 Dmitry Antipov <dmantipov@yandex.ru> | ||
| 2 | |||
| 3 | Change object marking routines to minimize stack usage. | ||
| 4 | This change moves a few cold paths from mark_object to NO_INLINE | ||
| 5 | functions and adjusts symbol marking loop. According to GCC 4.8.2 | ||
| 6 | -Wstack-usage, this reduces mark_object's stack usage from 80 to | ||
| 7 | 48 bytes on a 64-bit system. For a long byte-force-recompile runs, | ||
| 8 | stack usage at the mark phase is reduced up to 28%. Surprisingly, | ||
| 9 | it also gains up to 3% in speed (with default '-O2 -g3' flags). | ||
| 10 | * alloc.c (mark_compiled, mark_localized_symbol): New functions, | ||
| 11 | refactored out from ... | ||
| 12 | (mark_object): ... adjusted user. Also mark symbols in a tight | ||
| 13 | inner loop. | ||
| 14 | (mark_face_cache): Add NO_INLINE. | ||
| 15 | |||
| 1 | 2014-06-08 Eli Zaretskii <eliz@gnu.org> | 16 | 2014-06-08 Eli Zaretskii <eliz@gnu.org> |
| 2 | 17 | ||
| 3 | * sysdep.c (reset_sys_modes): Use cursorX, not curX, as the latter | 18 | * sysdep.c (reset_sys_modes): Use cursorX, not curX, as the latter |
diff --git a/src/alloc.c b/src/alloc.c index 60b035e6028..98a35853e02 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -5974,6 +5974,19 @@ mark_char_table (struct Lisp_Vector *ptr) | |||
| 5974 | } | 5974 | } |
| 5975 | } | 5975 | } |
| 5976 | 5976 | ||
| 5977 | NO_INLINE /* To reduce stack depth in mark_object. */ | ||
| 5978 | static Lisp_Object | ||
| 5979 | mark_compiled (struct Lisp_Vector *ptr) | ||
| 5980 | { | ||
| 5981 | int i, size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; | ||
| 5982 | |||
| 5983 | VECTOR_MARK (ptr); | ||
| 5984 | for (i = 0; i < size; i++) | ||
| 5985 | if (i != COMPILED_CONSTANTS) | ||
| 5986 | mark_object (ptr->contents[i]); | ||
| 5987 | return size > COMPILED_CONSTANTS ? ptr->contents[COMPILED_CONSTANTS] : Qnil; | ||
| 5988 | } | ||
| 5989 | |||
| 5977 | /* Mark the chain of overlays starting at PTR. */ | 5990 | /* Mark the chain of overlays starting at PTR. */ |
| 5978 | 5991 | ||
| 5979 | static void | 5992 | static void |
| @@ -6014,6 +6027,7 @@ mark_buffer (struct buffer *buffer) | |||
| 6014 | 6027 | ||
| 6015 | /* Mark Lisp faces in the face cache C. */ | 6028 | /* Mark Lisp faces in the face cache C. */ |
| 6016 | 6029 | ||
| 6030 | NO_INLINE /* To reduce stack depth in mark_object. */ | ||
| 6017 | static void | 6031 | static void |
| 6018 | mark_face_cache (struct face_cache *c) | 6032 | mark_face_cache (struct face_cache *c) |
| 6019 | { | 6033 | { |
| @@ -6036,6 +6050,24 @@ mark_face_cache (struct face_cache *c) | |||
| 6036 | } | 6050 | } |
| 6037 | } | 6051 | } |
| 6038 | 6052 | ||
| 6053 | NO_INLINE /* To reduce stack depth in mark_object. */ | ||
| 6054 | static void | ||
| 6055 | mark_localized_symbol (struct Lisp_Symbol *ptr) | ||
| 6056 | { | ||
| 6057 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr); | ||
| 6058 | Lisp_Object where = blv->where; | ||
| 6059 | /* If the value is set up for a killed buffer or deleted | ||
| 6060 | frame, restore it's global binding. If the value is | ||
| 6061 | forwarded to a C variable, either it's not a Lisp_Object | ||
| 6062 | var, or it's staticpro'd already. */ | ||
| 6063 | if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where))) | ||
| 6064 | || (FRAMEP (where) && !FRAME_LIVE_P (XFRAME (where)))) | ||
| 6065 | swap_in_global_binding (ptr); | ||
| 6066 | mark_object (blv->where); | ||
| 6067 | mark_object (blv->valcell); | ||
| 6068 | mark_object (blv->defcell); | ||
| 6069 | } | ||
| 6070 | |||
| 6039 | /* Remove killed buffers or items whose car is a killed buffer from | 6071 | /* Remove killed buffers or items whose car is a killed buffer from |
| 6040 | LIST, and mark other items. Return changed LIST, which is marked. */ | 6072 | LIST, and mark other items. Return changed LIST, which is marked. */ |
| 6041 | 6073 | ||
| @@ -6180,22 +6212,13 @@ mark_object (Lisp_Object arg) | |||
| 6180 | break; | 6212 | break; |
| 6181 | 6213 | ||
| 6182 | case PVEC_COMPILED: | 6214 | case PVEC_COMPILED: |
| 6183 | { /* We could treat this just like a vector, but it is better | 6215 | /* Although we could treat this just like a vector, mark_compiled |
| 6184 | to save the COMPILED_CONSTANTS element for last and avoid | 6216 | returns the COMPILED_CONSTANTS element, which is marked at the |
| 6185 | recursion there. */ | 6217 | next iteration of goto-loop here. This is done to avoid a few |
| 6186 | int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; | 6218 | recursive calls to mark_object. */ |
| 6187 | int i; | 6219 | obj = mark_compiled (ptr); |
| 6188 | 6220 | if (!NILP (obj)) | |
| 6189 | VECTOR_MARK (ptr); | 6221 | goto loop; |
| 6190 | for (i = 0; i < size; i++) | ||
| 6191 | if (i != COMPILED_CONSTANTS) | ||
| 6192 | mark_object (ptr->contents[i]); | ||
| 6193 | if (size > COMPILED_CONSTANTS) | ||
| 6194 | { | ||
| 6195 | obj = ptr->contents[COMPILED_CONSTANTS]; | ||
| 6196 | goto loop; | ||
| 6197 | } | ||
| 6198 | } | ||
| 6199 | break; | 6222 | break; |
| 6200 | 6223 | ||
| 6201 | case PVEC_FRAME: | 6224 | case PVEC_FRAME: |
| @@ -6283,8 +6306,7 @@ mark_object (Lisp_Object arg) | |||
| 6283 | case Lisp_Symbol: | 6306 | case Lisp_Symbol: |
| 6284 | { | 6307 | { |
| 6285 | register struct Lisp_Symbol *ptr = XSYMBOL (obj); | 6308 | register struct Lisp_Symbol *ptr = XSYMBOL (obj); |
| 6286 | struct Lisp_Symbol *ptrx; | 6309 | nextsym: |
| 6287 | |||
| 6288 | if (ptr->gcmarkbit) | 6310 | if (ptr->gcmarkbit) |
| 6289 | break; | 6311 | break; |
| 6290 | CHECK_ALLOCATED_AND_LIVE (live_symbol_p); | 6312 | CHECK_ALLOCATED_AND_LIVE (live_symbol_p); |
| @@ -6304,21 +6326,8 @@ mark_object (Lisp_Object arg) | |||
| 6304 | break; | 6326 | break; |
| 6305 | } | 6327 | } |
| 6306 | case SYMBOL_LOCALIZED: | 6328 | case SYMBOL_LOCALIZED: |
| 6307 | { | 6329 | mark_localized_symbol (ptr); |
| 6308 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr); | 6330 | break; |
| 6309 | Lisp_Object where = blv->where; | ||
| 6310 | /* If the value is set up for a killed buffer or deleted | ||
| 6311 | frame, restore it's global binding. If the value is | ||
| 6312 | forwarded to a C variable, either it's not a Lisp_Object | ||
| 6313 | var, or it's staticpro'd already. */ | ||
| 6314 | if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where))) | ||
| 6315 | || (FRAMEP (where) && !FRAME_LIVE_P (XFRAME (where)))) | ||
| 6316 | swap_in_global_binding (ptr); | ||
| 6317 | mark_object (blv->where); | ||
| 6318 | mark_object (blv->valcell); | ||
| 6319 | mark_object (blv->defcell); | ||
| 6320 | break; | ||
| 6321 | } | ||
| 6322 | case SYMBOL_FORWARDED: | 6331 | case SYMBOL_FORWARDED: |
| 6323 | /* If the value is forwarded to a buffer or keyboard field, | 6332 | /* If the value is forwarded to a buffer or keyboard field, |
| 6324 | these are marked when we see the corresponding object. | 6333 | these are marked when we see the corresponding object. |
| @@ -6330,14 +6339,10 @@ mark_object (Lisp_Object arg) | |||
| 6330 | if (!PURE_POINTER_P (XSTRING (ptr->name))) | 6339 | if (!PURE_POINTER_P (XSTRING (ptr->name))) |
| 6331 | MARK_STRING (XSTRING (ptr->name)); | 6340 | MARK_STRING (XSTRING (ptr->name)); |
| 6332 | MARK_INTERVAL_TREE (string_intervals (ptr->name)); | 6341 | MARK_INTERVAL_TREE (string_intervals (ptr->name)); |
| 6333 | 6342 | /* Inner loop to mark next symbol in this bucket, if any. */ | |
| 6334 | ptr = ptr->next; | 6343 | ptr = ptr->next; |
| 6335 | if (ptr) | 6344 | if (ptr) |
| 6336 | { | 6345 | goto nextsym; |
| 6337 | ptrx = ptr; /* Use of ptrx avoids compiler bug on Sun. */ | ||
| 6338 | XSETSYMBOL (obj, ptrx); | ||
| 6339 | goto loop; | ||
| 6340 | } | ||
| 6341 | } | 6346 | } |
| 6342 | break; | 6347 | break; |
| 6343 | 6348 | ||