[gcc(refs/users/iains/heads/d-for-darwin)] D, Darwin : Re-implement callWithStackShell for X86 Darwin.

Iain D Sandoe iains@gcc.gnu.org
Mon Jan 11 21:26:47 GMT 2021


https://gcc.gnu.org/g:0bef0580b4a93c2bf3c16e68fc91daaf6eccae08

commit 0bef0580b4a93c2bf3c16e68fc91daaf6eccae08
Author: Iain Sandoe <iain@sandoe.co.uk>
Date:   Thu Dec 10 14:13:55 2020 +0000

    D, Darwin : Re-implement callWithStackShell for X86 Darwin.
    
    At present, Darwin is using a generic solution to exposing the
    callee-saved registers to the GC.  This uses __builtin_unwind_init ().
    followed by an assignment to an address-taken variable to mark the
    stack bottom.
    
    This has two issues:
    1) On some archs it stores a huge amount of FP and Vector state which
        is not the subject of the scan - and, indeed might produce false hits.
    
    2) Even on archs like X86, without callee-saved FPRs/VRs there tend to
        be 'holes' in the frame allocations (to deal with alignment) which also
       will  contain random data which could produce false positives.
    
    The replacement solution stores only the integer callee-saved registers and
    then arranges a pointer to those.

Diff:
---
 libphobos/libdruntime/core/thread.d | 143 +++++++++++++++++++++++-------------
 1 file changed, 92 insertions(+), 51 deletions(-)

diff --git a/libphobos/libdruntime/core/thread.d b/libphobos/libdruntime/core/thread.d
index 715f14e9b71..d6506cda036 100644
--- a/libphobos/libdruntime/core/thread.d
+++ b/libphobos/libdruntime/core/thread.d
@@ -2430,73 +2430,114 @@ body
     // The purpose of the 'shell' is to ensure all the registers get
     // put on the stack so they'll be scanned. We only need to push
     // the callee-save registers.
-    void *sp = void;
 
-    version (GNU)
-    {
-        __builtin_unwind_init();
-        sp = &sp;
-    }
-    else version (AsmX86_Posix)
+    version (Darwin)
     {
-        size_t[3] regs = void;
-        asm pure nothrow @nogc
+        // The generic solution below using a call to __builtin_unwind_init ()
+        // followed by an assignment to sp has two issues:
+        // 1) On some archs it stores a huge amount of FP and Vector state which
+        //    is not the subject of the scan - and, indeed might produce false
+        //    hits.
+        // 2) Even on archs like X86, where there are no callee-saved FPRs/VRs there
+        //    tend to be 'holes' in the frame allocations (to deal with alignment) which
+        //    also will  contain random data which could produce false positives.
+        // This solution stores only the integer callee-saved registers.
+        version (X86)
         {
-            mov [regs + 0 * 4], EBX;
-            mov [regs + 1 * 4], ESI;
-            mov [regs + 2 * 4], EDI;
-
-            mov sp[EBP], ESP;
+            void*[4] regs = void;
+            asm pure nothrow @nogc
+            {
+                "movl   %%ebx, %0" : "=m" (regs[1]);
+                "movl   %%esi, %0" : "=m" (regs[2]);
+                "movl   %%edi, %0" : "=m" (regs[3]);
+            }
+            regs[0] = cast(void*)&regs[0];
+            fn (regs[0]);
+        }
+        else version (X86_64)
+        {
+            void*[6] regs = void;
+            asm pure nothrow @nogc
+            {
+                "movq   %%rbx, %0" : "=m" (regs[1]);
+                "movq   %%r12, %0" : "=m" (regs[2]);
+                "movq   %%r13, %0" : "=m" (regs[3]);
+                "movq   %%r14, %0" : "=m" (regs[4]);
+                "movq   %%r15, %0" : "=m" (regs[5]);
+            }
+            regs[0] = cast(void*)&regs[0];
+            fn (regs[0]);
         }
     }
-    else version (AsmX86_Windows)
+    else
     {
-        size_t[3] regs = void;
-        asm pure nothrow @nogc
+        void *sp = void;
+        version (GNU)
+        {
+            __builtin_unwind_init();
+            sp = &sp;
+        }
+        else version (AsmX86_Posix)
         {
-            mov [regs + 0 * 4], EBX;
-            mov [regs + 1 * 4], ESI;
-            mov [regs + 2 * 4], EDI;
+            size_t[3] regs = void;
+            asm pure nothrow @nogc
+            {
+                mov [regs + 0 * 4], EBX;
+                mov [regs + 1 * 4], ESI;
+                mov [regs + 2 * 4], EDI;
 
-            mov sp[EBP], ESP;
+                mov sp[EBP], ESP;
+            }
         }
-    }
-    else version (AsmX86_64_Posix)
-    {
-        size_t[5] regs = void;
-        asm pure nothrow @nogc
+        else version (AsmX86_Windows)
         {
-            mov [regs + 0 * 8], RBX;
-            mov [regs + 1 * 8], R12;
-            mov [regs + 2 * 8], R13;
-            mov [regs + 3 * 8], R14;
-            mov [regs + 4 * 8], R15;
+            size_t[3] regs = void;
+            asm pure nothrow @nogc
+            {
+                mov [regs + 0 * 4], EBX;
+                mov [regs + 1 * 4], ESI;
+                mov [regs + 2 * 4], EDI;
 
-            mov sp[RBP], RSP;
+                mov sp[EBP], ESP;
+            }
         }
-    }
-    else version (AsmX86_64_Windows)
-    {
-        size_t[7] regs = void;
-        asm pure nothrow @nogc
+        else version (AsmX86_64_Posix)
         {
-            mov [regs + 0 * 8], RBX;
-            mov [regs + 1 * 8], RSI;
-            mov [regs + 2 * 8], RDI;
-            mov [regs + 3 * 8], R12;
-            mov [regs + 4 * 8], R13;
-            mov [regs + 5 * 8], R14;
-            mov [regs + 6 * 8], R15;
+            size_t[5] regs = void;
+            asm pure nothrow @nogc
+            {
+                mov [regs + 0 * 8], RBX;
+                mov [regs + 1 * 8], R12;
+                mov [regs + 2 * 8], R13;
+                mov [regs + 3 * 8], R14;
+                mov [regs + 4 * 8], R15;
 
-            mov sp[RBP], RSP;
+                mov sp[RBP], RSP;
+            }
+        }
+        else version (AsmX86_64_Windows)
+        {
+            size_t[7] regs = void;
+            asm pure nothrow @nogc
+            {
+                mov [regs + 0 * 8], RBX;
+                mov [regs + 1 * 8], RSI;
+                mov [regs + 2 * 8], RDI;
+                mov [regs + 3 * 8], R12;
+                mov [regs + 4 * 8], R13;
+                mov [regs + 5 * 8], R14;
+                mov [regs + 6 * 8], R15;
+
+                mov sp[RBP], RSP;
+            }
+        }
+        else
+        {
+            static assert(false, "Architecture not supported.");
         }
-    }
-    else
-    {
-        static assert(false, "Architecture not supported.");
-    }
 
-    fn(sp);
+        fn(sp);
+    }
 }
 
 // Used for suspendAll/resumeAll below.


More information about the Gcc-cvs mailing list