aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDmitry Antipov2014-06-08 19:06:03 +0400
committerDmitry Antipov2014-06-08 19:06:03 +0400
commit83f1450065c55a3e5dce5db0da737cb7a6a4d60c (patch)
tree92d118deaa0a9a24d48aa22353c5c413377267d7 /src
parent36cf8493aff99b652b2ad8c9e4d55a18688e8484 (diff)
downloademacs-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/ChangeLog15
-rw-r--r--src/alloc.c83
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 @@
12014-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
12014-06-08 Eli Zaretskii <eliz@gnu.org> 162014-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
5977NO_INLINE /* To reduce stack depth in mark_object. */
5978static Lisp_Object
5979mark_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
5979static void 5992static 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
6030NO_INLINE /* To reduce stack depth in mark_object. */
6017static void 6031static void
6018mark_face_cache (struct face_cache *c) 6032mark_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
6053NO_INLINE /* To reduce stack depth in mark_object. */
6054static void
6055mark_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