Replace push_one calls with push_many_regs one for Win32 thread context
authorIvan Maidanski <ivmai@mail.ru>
Tue, 10 Sep 2019 08:09:42 +0000 (11:09 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 10 Sep 2019 15:32:05 +0000 (18:32 +0300)
(code refactoring)

Also, do not define GC_push_one except for Darwin (and some ancient
targets that use the function).

* include/private/gc_priv.h [MSWIN32 || MSWINCE] (GC_push_one): Do not
declare.
* include/private/gc_priv.h [!MSWIN32 && !MSWINCE] (GC_push_one):
Declare only if AMIGA or MACOS or GC_DARWIN_THREADS.
* include/private/gc_priv.h [GC_WIN32_THREADS] (GC_push_many_regs):
Declare function; add comment.
* mark.c (GC_push_one): Define only if AMIGA or MACOS or
GC_DARWIN_THREADS.
* mark.c [GC_WIN32_THREADS] (GC_push_many_regs): New GC_INNER function.
* win32_threads.c (GC_push_stack_for): Remove i local variable; call
GC_push_many_regs() instead of a loop with GC_push_one() calls (ignore
2 first registers if WOW64_THREAD_CONTEXT_WORKAROUND).

include/private/gc_priv.h
mark.c
win32_threads.c

index 1124a80..ef81ae6 100644 (file)
@@ -1766,11 +1766,9 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *),
   /* pointer to the top of the corresponding memory stack.              */
   ptr_t GC_save_regs_in_stack(void);
 #endif
-                        /* Push register contents onto mark stack.      */
 
-#if defined(MSWIN32) || defined(MSWINCE)
-  void __cdecl GC_push_one(word p);
-#else
+                        /* Push register contents onto mark stack.      */
+#if defined(AMIGA) || defined(MACOS) || defined(GC_DARWIN_THREADS)
   void GC_push_one(word p);
                               /* If p points to an object, mark it    */
                               /* and push contents on the mark stack  */
@@ -1780,6 +1778,11 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *),
                               /* stack.                               */
 #endif
 
+#ifdef GC_WIN32_THREADS
+  /* Same as GC_push_one but for a sequence of registers.       */
+  GC_INNER void GC_push_many_regs(const word *regs, unsigned count);
+#endif
+
 #if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS)
   GC_INNER void GC_mark_and_push_stack(ptr_t p, ptr_t source);
                                 /* Ditto, omits plausibility test       */
diff --git a/mark.c b/mark.c
index 8cd13f5..4d702a9 100644 (file)
--- a/mark.c
+++ b/mark.c
@@ -1428,14 +1428,21 @@ GC_API void GC_CALL GC_push_all(void *bottom, void *top)
   }
 #endif /* GC_DISABLE_INCREMENTAL */
 
-#if defined(MSWIN32) || defined(MSWINCE)
-  void __cdecl GC_push_one(word p)
-#else
+#if defined(AMIGA) || defined(MACOS) || defined(GC_DARWIN_THREADS)
   void GC_push_one(word p)
-#endif
-{
+  {
     GC_PUSH_ONE_STACK(p, MARKED_FROM_REGISTER);
-}
+  }
+#endif
+
+#ifdef GC_WIN32_THREADS
+  GC_INNER void GC_push_many_regs(const word *regs, unsigned count)
+  {
+    unsigned i;
+    for (i = 0; i < count; i++)
+      GC_PUSH_ONE_STACK(regs[i], MARKED_FROM_REGISTER);
+  }
+#endif
 
 GC_API struct GC_ms_entry * GC_CALL GC_mark_and_push(void *obj,
                                                 mse *mark_stack_ptr,
index 10bf651..5a35e70 100644 (file)
@@ -1585,7 +1585,6 @@ STATIC word GC_push_stack_for(GC_thread thread, DWORD me)
     sp = GC_approx_sp();
   } else if ((sp = thread -> thread_blocked_sp) == NULL) {
               /* Use saved sp value for blocked threads. */
-    int i = 0;
 #   ifdef RETRY_GET_THREAD_CONTEXT
       /* We cache context when suspending the thread since it may       */
       /* require looping.                                               */
@@ -1605,13 +1604,12 @@ STATIC word GC_push_stack_for(GC_thread thread, DWORD me)
       }
 #   endif
 
-#   ifdef WOW64_THREAD_CONTEXT_WORKAROUND
-      i += 2; /* skip ContextFlags and SegFs */
-#   endif
-    for (; i < PUSHED_REGS_COUNT; i++)
-      GC_push_one(regs[i]);
+#   ifndef WOW64_THREAD_CONTEXT_WORKAROUND
+      GC_push_many_regs(regs, PUSHED_REGS_COUNT);
+#   else
+      GC_push_many_regs(regs + 2, PUSHED_REGS_COUNT - 2);
+                                        /* skip ContextFlags and SegFs */
 
-#   ifdef WOW64_THREAD_CONTEXT_WORKAROUND
       /* WoW64 workaround. */
       if (isWow64) {
         DWORD ContextFlags = (DWORD)regs[0];