Index: /trunk/src/libs/xpcom18a4/Config.kmk
===================================================================
--- /trunk/src/libs/xpcom18a4/Config.kmk	(revision 87253)
+++ /trunk/src/libs/xpcom18a4/Config.kmk	(revision 87254)
@@ -51,4 +51,5 @@
 TEMPLATE_XPCOM_CXXFLAGS.x86        = -m32
 TEMPLATE_XPCOM_CXXFLAGS.amd64      = -m64
+TEMPLATE_XPCOM_CXXFLAGS.arm64      = -m64
 TEMPLATE_XPCOM_CXXFLAGS.darwin     = -fpascal-strings -fshort-wchar -fno-common -fno-rtti $(VBOX_DARWIN_DEF_SDK_CXXFLAGS)
 TEMPLATE_XPCOM_CXXFLAGS.freebsd    = -pthread
@@ -59,4 +60,5 @@
 TEMPLATE_XPCOM_CFLAGS.x86          = -m32
 TEMPLATE_XPCOM_CFLAGS.amd64        = -m64
+TEMPLATE_XPCOM_CFLAGS.arm64        = -m64
 TEMPLATE_XPCOM_CFLAGS.freebsd      = -pthread
 TEMPLATE_XPCOM_CFLAGS.linux        = -pthread -ansi
@@ -75,6 +77,8 @@
 TEMPLATE_XPCOM_DEFS.x86            = i386=1
 TEMPLATE_XPCOM_DEFS.amd64          = HAVE_VA_LIST_AS_ARRAY HAVE_VA_COPY VA_COPY\(a\,b\)=__builtin_va_copy\(a\,b\)
+TEMPLATE_XPCOM_DEFS.arm64          = HAVE_VA_LIST_AS_ARRAY HAVE_VA_COPY VA_COPY\(a\,b\)=__builtin_va_copy\(a\,b\)
 TEMPLATE_XPCOM_DEFS.darwin         = OSTYPE=\"Darwin8.8.1\" OSARCH=\"Darwin\" XP_UNIX=1 XP_MACOSX=1 TARGET_CARBON=1 HAVE_VISIBILITY_ATTRIBUTE=1 DARWIN=1 $(TEMPLATE_VBOXR3NP_DEFS.darwin)
 TEMPLATE_XPCOM_DEFS.darwin.amd64   = VBOX_MACOSX_FOLLOWS_UNIX_IO
+TEMPLATE_XPCOM_DEFS.darwin.arm64   = VBOX_MACOSX_FOLLOWS_UNIX_IO
 TEMPLATE_XPCOM_DEFS.freebsd        = OSTYPE=\"FreeBSD5+\"   OSARCH=\"FreeBSD\" XP_UNIX=1 FREEBSD=1 HAVE_VISIBILITY_ATTRIBUTE=1
 TEMPLATE_XPCOM_DEFS.linux          = OSTYPE=\"Linux2.6\"    OSARCH=\"Linux\"  XP_UNIX=1 _GNU_SOURCE HAVE_VISIBILITY_ATTRIBUTE=1 ## @todo LINUX=1
@@ -90,4 +94,5 @@
 TEMPLATE_XPCOM_LDFLAGS.x86         = -m32
 TEMPLATE_XPCOM_LDFLAGS.amd64       = -m64
+TEMPLATE_XPCOM_LDFLAGS.arm64       = -m64
 TEMPLATE_XPCOM_LDFLAGS.darwin      = $(TEMPLATE_VBOXR3NP_LDFLAGS.darwin) \
 	-fshort-wchar -fno-rtti -fno-exceptions -fpascal-strings \
Index: /trunk/src/libs/xpcom18a4/Makefile.kmk
===================================================================
--- /trunk/src/libs/xpcom18a4/Makefile.kmk	(revision 87253)
+++ /trunk/src/libs/xpcom18a4/Makefile.kmk	(revision 87254)
@@ -516,4 +516,6 @@
 VBox-xpcom-nspr_DEFS.darwin.amd64 = \
 	VBOX_USE_MORE_IPRT_IN_NSPR
+VBox-xpcom-nspr_DEFS.darwin.arm64 = \
+	VBOX_USE_MORE_IPRT_IN_NSPR
 VBox-xpcom-nspr_DEFS.darwin = \
 	HAVE_BSD_FLOCK=1 \
@@ -805,5 +807,5 @@
 	xpcom/MoreFiles/FSCopyObject.c \
 	xpcom/MoreFiles/MoreFilesX.c
-if1of ($(KBUILD_TARGET) $(KBUILD_TARGET).$(KBUILD_TARGET_ARCH), freebsd linux netbsd openbsd solaris darwin.amd64)
+if1of ($(KBUILD_TARGET) $(KBUILD_TARGET).$(KBUILD_TARGET_ARCH), freebsd linux netbsd openbsd solaris darwin.amd64 darwin.arm64)
 VBox-xpcom-io_SOURCES += \
 	xpcom/io/nsLocalFileUnix.cpp
@@ -875,4 +877,6 @@
                                            xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_solaris.cpp
 VBox-xpcom-xptcall_SOURCES.amd64         = xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_vbox.asm
+VBox-xpcom-xptcall_SOURCES.arm64         = xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm64_vbox.cpp \
+                                           xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm64_vbox.cpp
 VBox-xpcom-xptcall_SOURCES.darwin.amd64  = xpcom/reflect/xptcall/src/md/unix/xptcstubs_amd64_darwin.cpp # Underscore prefix.
 VBox-xpcom-xptcall_SOURCES.freebsd.amd64 = xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp
Index: /trunk/src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.cfg
===================================================================
--- /trunk/src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.cfg	(revision 87253)
+++ /trunk/src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.cfg	(revision 87254)
@@ -49,5 +49,5 @@
 #define PR_AF_INET6 30  /* same as AF_INET6 */
 
-#if defined(i386) || defined(__i386__) || defined(__amd64__)
+#if defined(i386) || defined(__i386__) || defined(__amd64__) || defined(__arm64__) || defined(__arm__)
 #undef IS_BIG_ENDIAN
 #define  IS_LITTLE_ENDIAN 1
Index: /trunk/src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.h
===================================================================
--- /trunk/src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.h	(revision 87253)
+++ /trunk/src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.h	(revision 87254)
@@ -55,4 +55,8 @@
 #elif defined(__amd64__)
 #define _PR_SI_ARCHITECTURE "amd64"
+#elif defined(__arm__)
+#define _PR_SI_ARCHITECTURE "arm"
+#elif defined(__arm64__)
+#define _PR_SI_ARCHITECTURE "arm64"
 #else
 #error "unknown architecture."
Index: /trunk/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.cpp
===================================================================
--- /trunk/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.cpp	(revision 87253)
+++ /trunk/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.cpp	(revision 87254)
@@ -150,5 +150,5 @@
 #if (defined (XP_MAC) || defined(XP_MACOSX)) && !defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
     short foundVRefNum;
-    long foundDirID;
+    SInt32 foundDirID;
     FSSpec fileSpec;
     nsCOMPtr<nsILocalFileMac> macFile;
@@ -588,5 +588,5 @@
         if (!keys) {
             OSErr err;
-            long response;
+            SInt32 response;
             err = ::Gestalt(gestaltSystemVersion, &response);
             keys = (!err && response >= 0x00001000) ? osXKeys : os9Keys;
Index: /trunk/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm64_vbox.cpp
===================================================================
--- /trunk/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm64_vbox.cpp	(revision 87254)
+++ /trunk/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm64_vbox.cpp	(revision 87254)
@@ -0,0 +1,285 @@
+/* $Id$ */
+/** @file
+ * XPCOM - Implementation XPTC_InvokeByIndex for arm64.
+ */
+
+/*
+ * Copyright (C) 2021 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "xptcprivate.h"
+#include <iprt/cdefs.h>
+#include <iprt/alloca.h>
+#include <iprt/assert.h>
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+#define NUM_ARGS_IN_GPRS    8   /**< Number of arguments passed in general purpose registers (starting with x0). */
+#define NUM_ARGS_IN_FPRS    8   /**< Number of arguments passed in floating point registers (starting with d0). */
+
+#define MY_MAX_ARGS         64  /**< Limit ourselves to 64 arguments. */
+
+
+
+AssertCompileMemberOffset(nsXPTCVariant, val, 0);
+
+extern "C" __attribute__((naked)) nsresult
+arm64AsmInvoker(uintptr_t pfnMethod /*x0*/, uint32_t cParams /*w1*/, nsXPTCVariant *paParams /*x2*/, uint64_t cbStack /*x3*/,
+                uint8_t *acbStackArgs /*x4*/, uint64_t *pauGprArgs /*x5*/, uint64_t *pauFprArgs /*x6*/, uint32_t cFprArgs /*x7*/)
+{
+    __asm__ __volatile__(
+        /* Prologue - create the frame. */ "\
+        sub     sp, sp, 16 \n\
+        stp     x29, x30, [sp] \n\
+        mov     x29, sp \n\
+        .cfi_def_cfa        x29, 16 \n\
+        .cfi_rel_offset     x30, -8 \n\
+        .cfi_rel_offset     x29, -16 \n\
+\n\
+"       /* Move pfnMethod to x16 and pauGprArgs to x7 free up x0 and x5: */ "\
+        mov     x16, x0 \n\
+        mov     x17, x5 \n\
+\n\
+"       /* Load FPU registers first so we free up x6 & x7 early: */ "\
+        cmp     w7, #0 \n\
+        b.eq    Lno_fprs\n\
+        ldp     d0, d1, [x6] \n\
+        ldp     d2, d3, [x6, #16] \n\
+        ldp     d4, d5, [x6, #32] \n\
+        ldp     d6, d7, [x6, #48] \n\
+Lno_fprs:\n\
+\n\
+"       /* Do argument passing by stack (if any).  We align the stack to 16 bytes.  */ "\
+        cmp     x3, #0 \n\
+        beq     Lno_stack_args \n\
+        sub     x3, sp, x3 \n\
+        bic     x3, x3, #15 \n\
+        mov     sp, x3 \n\
+Lnext_parameter: \n\
+        ldrb    w7, [x4] \n\
+        cmp     w7, #0 \n\
+        beq     Ladvance\n\
+\n\
+        cmp     w7, #4 \n\
+        bgt     Lstore_64bits\n\
+        cmp     w7, #1 \n\
+        beq     Lstore_8bits\n\
+        cmp     w7, #2 \n\
+        beq     Lstore_16bits\n\
+\n\
+Lstore_32bits:\n\
+        ldr     w0, [x2] \n\
+        add     x3, x3, #3 \n\
+        bic     x3, x3, #3 \n\
+        str     w0, [x3] \n"
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+"       add     x3, x3, #4 \n"
+#endif
+"       b       Ladvance \n\
+\n\
+Lstore_8bits:\n\
+        ldrb    w0, [x2] \n\
+        strb    w0, [x3] \n"
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+"       add     x3, x3, #1 \n"
+#endif
+"       b       Ladvance \n\
+\n\
+Lstore_16bits:\n\
+        ldrh    w0, [x2] \n\
+        add     x3, x3, #1 \n\
+        bic     x3, x3, #1 \n\
+        strh    w0, [x3] \n"
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+"       add     x3, x3, #2 \n"
+#endif
+"       b       Ladvance \n\
+\n\
+Lstore_64bits_ptr:\n\
+        ldr     x0, [x2, %[offPtrInXPTCVariant]] \n\
+        b       Lstore_64bits_common \n\
+Lstore_64bits:\n\
+        tst     w7, #0x80 \n\
+        bne     Lstore_64bits_ptr \n\
+        ldr     x0, [x2] \n\
+Lstore_64bits_common:\n\
+        add     x3, x3, #7 \n\
+        bic     x3, x3, #7 \n\
+        str     x0, [x3] \n"
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+"       add     x3, x3, #8 \n"
+#endif
+"\n\
+Ladvance:\n"
+#ifndef RT_OS_DARWIN /* macOS compacts stack usage. */
+"       add     x3, x3, #8 \n"
+#endif
+"       add     x4, x4, #1 \n\
+        add     x2, x2, %[cbXPTCVariant] \n\
+        sub     w1, w1, #1 \n\
+        cmp     w1, #0 \n\
+        bne     Lnext_parameter \n\
+\n\
+"       /* reserve stack space for the integer and floating point registers and save them: */ "\
+Lno_stack_args: \n\
+\n\
+"       /* Load general purpose argument registers: */ "\
+        ldp     x0, x1, [x17] \n\
+        ldp     x2, x3, [x17, #16] \n\
+        ldp     x4, x5, [x17, #32] \n\
+        ldp     x6, x7, [x17, #48] \n\
+\n\
+"       /* Make the call: */ "\
+        blr     x16 \n\
+\n\
+"       /* Epilogue (clang does not emit the .cfi's here, so drop them too?): */ "\
+        mov     sp, x29 \n\
+        ldp	x29, x30, [sp] \n\
+        add     sp, sp, #16 \n\
+        .cfi_def_cfa sp, 0 \n\
+        .cfi_restore x29 \n\
+        .cfi_restore x30 \n\
+        ret \n\
+"   :
+    : [cbXPTCVariant] "i" (sizeof(nsXPTCVariant))
+    , [offPtrInXPTCVariant] "i" (offsetof(nsXPTCVariant, ptr))
+    :);
+}
+
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports *pThis, PRUint32 idxMethod, PRUint32 cParams, nsXPTCVariant *paParams)
+{
+    AssertMsgReturn(cParams <= MY_MAX_ARGS, ("cParams=%#x idxMethod=%#x\n", cParams, idxMethod), NS_ERROR_UNEXPECTED);
+
+    /*
+     * Prepare
+     */
+    uint64_t auGprArgs[NUM_ARGS_IN_GPRS] = {0};
+    uint64_t auFprArgs[NUM_ARGS_IN_GPRS] = {0};
+    uint8_t  acbStackArgs[MY_MAX_ARGS]; /* The number of value bytes to copy onto the stack. Zero if in register. */
+    uint32_t cbStackArgs = 0;
+    uint32_t cFprArgs    = 0;
+    uint32_t cGprArgs    = 0;
+
+    /* First argument is always 'pThis'. The 'pThis' argument is not accounted
+       for in cParams or acbStackArgs. */
+    auGprArgs[cGprArgs++] = (uintptr_t)pThis;
+
+    /* Do the other arguments. */
+    for (PRUint32 i = 0; i < cParams; i++)
+    {
+        if (paParams[i].IsPtrData())
+        {
+            if (cGprArgs < NUM_ARGS_IN_GPRS)
+            {
+                auGprArgs[cGprArgs++] = (uintptr_t)paParams[i].ptr;
+                acbStackArgs[i] = 0;
+            }
+            else
+            {
+                acbStackArgs[i] = sizeof(paParams[i].ptr) | UINT8_C(0x80);
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+                cbStackArgs     = RT_ALIGN_32(cbStackArgs, sizeof(paParams[i].ptr)) + sizeof(paParams[i].ptr);
+#else
+                cbStackArgs    += sizeof(uint64_t);
+#endif
+            }
+        }
+        else
+        {
+            if (   paParams[i].type != nsXPTType::T_FLOAT
+                 && paParams[i].type != nsXPTType::T_DOUBLE)
+            {
+                if (cGprArgs < NUM_ARGS_IN_GPRS)
+                {
+                    switch (paParams[i].type)
+                    {
+                        case nsXPTType::T_I8:       auGprArgs[cGprArgs++] = paParams[i].val.i8; break;
+                        case nsXPTType::T_I16:      auGprArgs[cGprArgs++] = paParams[i].val.i16; break;
+                        case nsXPTType::T_I32:      auGprArgs[cGprArgs++] = paParams[i].val.i32; break;
+                        case nsXPTType::T_I64:      auGprArgs[cGprArgs++] = paParams[i].val.i64; break;
+                        case nsXPTType::T_U8:       auGprArgs[cGprArgs++] = paParams[i].val.u8; break;
+                        case nsXPTType::T_U16:      auGprArgs[cGprArgs++] = paParams[i].val.u16; break;
+                        case nsXPTType::T_U32:      auGprArgs[cGprArgs++] = paParams[i].val.u32; break;
+                        default:
+                        case nsXPTType::T_U64:      auGprArgs[cGprArgs++] = paParams[i].val.u64; break;
+                        case nsXPTType::T_BOOL:     auGprArgs[cGprArgs++] = paParams[i].val.b; break;
+                        case nsXPTType::T_CHAR:     auGprArgs[cGprArgs++] = paParams[i].val.c; break;
+                        case nsXPTType::T_WCHAR:    auGprArgs[cGprArgs++] = paParams[i].val.wc; break;
+                    }
+                    acbStackArgs[i] = 0;
+                }
+                else
+                {
+                    uint8_t cbStack;
+                    switch (paParams[i].type)
+                    {
+                        case nsXPTType::T_I8:       cbStack = sizeof(paParams[i].val.i8); break;
+                        case nsXPTType::T_I16:      cbStack = sizeof(paParams[i].val.i16); break;
+                        case nsXPTType::T_I32:      cbStack = sizeof(paParams[i].val.i32); break;
+                        case nsXPTType::T_I64:      cbStack = sizeof(paParams[i].val.i64); break;
+                        case nsXPTType::T_U8:       cbStack = sizeof(paParams[i].val.u8); break;
+                        case nsXPTType::T_U16:      cbStack = sizeof(paParams[i].val.u16); break;
+                        case nsXPTType::T_U32:      cbStack = sizeof(paParams[i].val.u32); break;
+                        default:
+                        case nsXPTType::T_U64:      cbStack = sizeof(paParams[i].val.u64); break;
+                        case nsXPTType::T_BOOL:     cbStack = sizeof(paParams[i].val.b); break;
+                        case nsXPTType::T_CHAR:     cbStack = sizeof(paParams[i].val.c); break;
+                        case nsXPTType::T_WCHAR:    cbStack = sizeof(paParams[i].val.wc); break;
+                    }
+                    acbStackArgs[i] = cbStack;
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+                    cbStackArgs     = RT_ALIGN_32(cbStackArgs, cbStack) + cbStack;
+#else
+                    cbStackArgs    += sizeof(uint64_t);
+#endif
+                }
+            }
+            else if (cFprArgs < NUM_ARGS_IN_FPRS)
+            {
+                AssertCompile(sizeof(paParams[i].val.f) == 4);
+                AssertCompile(sizeof(paParams[i].val.d) == 8);
+                if (paParams[i].type == nsXPTType::T_FLOAT)
+                    auFprArgs[cFprArgs++] = paParams[i].val.u32;
+                else
+                    auFprArgs[cFprArgs++] = paParams[i].val.u64;
+                acbStackArgs[i] = 0;
+            }
+            else
+            {
+                uint8_t cbStack;
+                if (paParams[i].type == nsXPTType::T_FLOAT)
+                    cbStack = sizeof(paParams[i].val.f);
+                else
+                    cbStack = sizeof(paParams[i].val.d);
+                acbStackArgs[i] = cbStack;
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+                cbStackArgs     = RT_ALIGN_32(cbStackArgs, cbStack) + cbStack;
+#else
+                cbStackArgs    += sizeof(uint64_t);
+#endif
+            }
+        }
+    }
+
+    /*
+     * Pass it on to a naked wrapper function that does the nitty gritty work.
+     */
+    uintptr_t *pauVtable = *(uintptr_t **)pThis;
+    return arm64AsmInvoker(pauVtable[idxMethod], cParams, paParams, cbStackArgs, acbStackArgs, auGprArgs, auFprArgs, cFprArgs);
+}
+
Index: /trunk/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm64_vbox.cpp
===================================================================
--- /trunk/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm64_vbox.cpp	(revision 87254)
+++ /trunk/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm64_vbox.cpp	(revision 87254)
@@ -0,0 +1,261 @@
+/* $Id$ */
+/** @file
+ * XPCOM - XPTC stubs for arm64.
+ */
+
+/*
+ * Copyright (C) 2021 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "xptcprivate.h"
+#include <iprt/cdefs.h>
+#include <iprt/alloca.h>
+#include <iprt/assert.h>
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+#if defined(RT_OS_DARWIN)
+# define NAME_PREFIX        _
+# define NAME_PREFIX_STR    "_"
+#else
+# define NAME_PREFIX
+# define NAME_PREFIX_STR    ""
+#endif
+#define ASMNAME(a_Name)     NAME_PREFIX ## a_Name
+#define NUM_ARGS_IN_GPRS    8   /**< Number of arguments passed in general purpose registers (starting with x0). */
+#define NUM_ARGS_IN_FPRS    8   /**< Number of arguments passed in floating point registers (starting with d0). */
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+extern "C" __attribute__((naked)) nsresult CommonXPTCStub(void);
+DECL_NO_INLINE(extern "C", nsresult)
+CommonXPTCStubCWorker(nsXPTCStubBase *pThis, uint32_t idxMethod, uint64_t *pauGprArgs, uint64_t *pauFprArgs, uint64_t *puStackArgs);
+
+
+/**
+ * All the stubs call this shared code w/ method index in w17.
+ *
+ * The naked attribute means pure inline assembly function.  clang complains
+ * if we put C statements in it.  So, this exacty what we need here and for the
+ * stubs.
+ *
+ * @note This could be static if we weren't afraid the compile would optimize it
+ *       out.
+ */
+extern "C" __attribute__((naked)) nsresult CommonXPTCStub(void)
+{
+    __asm__ __volatile__(
+        /* Prologue - reserve space for frame+link reg spill and the GPR and FPR arrays. */ "\
+        sub     sp, sp, %[cbGPRandFPRs] + 16 \n\
+        stp     x29, x30, [sp, %[cbGPRandFPRs]] \n\
+        add     x29, sp, %[cbGPRandFPRs] \n\
+        .cfi_def_cfa        x29, 16 \n\
+        .cfi_rel_offset     x30, -8 \n\
+        .cfi_rel_offset     x29, -16 \n\
+"
+        /* reserve stack space for the integer and floating point registers and save them: */ "\
+        \n\
+        stp     x0, x1, [sp, #0] \n\
+        stp     x2, x3, [sp, #16] \n\
+        stp     x4, x5, [sp, #32] \n\
+        stp     x6, x7, [sp, #48] \n\
+        \n\
+        stp     d0, d1, [sp, %[cbGPRs]] \n\
+        stp     d2, d3, [sp, %[cbGPRs] + 16] \n\
+        stp     d4, d5, [sp, %[cbGPRs] + 32] \n\
+        stp     d6, d7, [sp, %[cbGPRs] + 48] \n\
+\n\
+"        /* Call the C worker. We keep x0 as is.
+           Set w1 to the w17 method index from the stubs. */ "\
+        mov     w1, w17 \n\
+        mov     x2, sp \n\
+        add     x3, sp, %[cbGPRs] \n\
+        add     x4, sp, %[cbGPRs] + 16 \n\
+        bl      " NAME_PREFIX_STR "CommonXPTCStubCWorker \n\
+"
+        /* Epilogue (clang does not emit the .cfi's here, so drop them too?): */ "\
+        ldp	x29, x30, [sp, %[cbGPRs]] \n\
+        add     sp, sp, %[cbGPRandFPRs] + 16 \n\
+        .cfi_def_cfa sp, 0 \n\
+        .cfi_restore x29 \n\
+        .cfi_restore x30 \n\
+        ret \n\
+"   :
+    : [cbGPRandFPRs] "i" (NUM_ARGS_IN_GPRS * 8 + NUM_ARGS_IN_FPRS * 8)
+    , [cbGPRs] "i" (NUM_ARGS_IN_GPRS * 8)
+    :);
+}
+
+#define STUB_ENTRY(n) \
+    __attribute__((naked)) nsresult nsXPTCStubBase::Stub##n() \
+    { \
+        __asm__ __volatile__ ("mov  w17, #" #n "\n\t"  \
+                              "b    " NAME_PREFIX_STR "CommonXPTCStub\n\t"); \
+    }
+
+#define SENTINEL_ENTRY(n) \
+    nsresult nsXPTCStubBase::Sentinel##n() \
+    { \
+        AssertMsgFailed(("nsXPTCStubBase::Sentinel" #n " called!\n")); \
+        return NS_ERROR_NOT_IMPLEMENTED; \
+    }
+
+/* Instantiate the stubs and sentinels  */
+#include "xptcstubsdef.inc"
+
+
+
+/*
+ * Function templates for fetching arguments
+ */
+
+template<typename Type> static inline void fetchStack(Type *pRet, uint64_t *&rpuStackArgs)
+{
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+    Type *pStackTmp = RT_ALIGN_PT(rpuStackArgs, sizeof(Type), Type *);
+    *pRet = *pStackTmp;
+    rpuStackArgs = (uint64_t *)(pStackTmp + 1);
+#else
+    *pRet = (Type)*rpuStackArgs++;
+#endif
+}
+
+template<typename Type> static inline void fetchFpr(Type *pRet, uint64_t *pauFprArgs, unsigned &ridxFpr, uint64_t *&rpuStackArgs)
+{
+    if (ridxFpr < NUM_ARGS_IN_FPRS)
+        *pRet = (Type)pauFprArgs[ridxFpr++];
+    else
+        fetchStack(pRet, rpuStackArgs);
+}
+
+
+template<typename Type> static inline void fetchGpr(Type *pRet, uint64_t *pauGprArgs, unsigned &ridxGpr, uint64_t *&rpuStackArgs)
+{
+    if (ridxGpr < NUM_ARGS_IN_GPRS)
+        *pRet = (Type)pauGprArgs[ridxGpr++];
+    else
+        fetchStack(pRet, rpuStackArgs);
+}
+
+
+/**
+ * Called by CommonXPTCStub below after it dumps registers and locates
+ * arguments on the stack (if any).
+ */
+DECL_NO_INLINE(extern "C", nsresult)
+CommonXPTCStubCWorker(nsXPTCStubBase *pThis, uint32_t idxMethod, uint64_t *pauGprArgs, uint64_t *pauFprArgs, uint64_t *puStackArgs)
+{
+    AssertReturn(pThis, NS_ERROR_UNEXPECTED);
+
+    /* Get method information: */
+    nsIInterfaceInfo *pInterfaceInfo = NULL;
+    nsresult hrc = pThis->GetInterfaceInfo(&pInterfaceInfo);
+    AssertReturn(NS_SUCCEEDED(hrc), hrc);
+    AssertReturn(pInterfaceInfo, NS_ERROR_UNEXPECTED);
+
+    const nsXPTMethodInfo *pMethodInfo;
+    hrc = pInterfaceInfo->GetMethodInfo((PRUint16)idxMethod, &pMethodInfo);
+    AssertReturn(NS_SUCCEEDED(hrc), hrc);
+    AssertReturn(pMethodInfo, NS_ERROR_UNEXPECTED);
+
+    /* Allocate dispatcher parameter array. */
+    PRUint8 const cParams = pMethodInfo->GetParamCount();
+    nsXPTCMiniVariant aParamsStatic[8];
+    nsXPTCMiniVariant *paParams;
+    if (cParams <= RT_ELEMENTS(aParamsStatic))
+        paParams = aParamsStatic;
+    else
+    {
+        paParams = (nsXPTCMiniVariant *)alloca(sizeof(paParams[0]) * cParams);
+        AssertReturn(paParams, NS_ERROR_UNEXPECTED);
+    }
+
+    /*
+     * Populate the dispatcher parameter array.
+     */
+    unsigned idxGprArgs = 0;
+    unsigned idxFprArgs = 0;
+    for (PRUint8 i = 0; i < cParams; i++)
+    {
+        const nsXPTParamInfo &rParam = pMethodInfo->GetParam(i);
+        if (rParam.IsOut())
+            fetchGpr(&paParams[i].val.p, pauGprArgs, idxGprArgs, puStackArgs);
+        else
+        {
+            const nsXPTType Type  = rParam.GetType();
+            switch (Type)
+            {
+                case nsXPTType::T_I8:       fetchGpr(&paParams[i].val.i8,  pauGprArgs, idxGprArgs, puStackArgs); break;
+                case nsXPTType::T_I16:      fetchGpr(&paParams[i].val.i16, pauGprArgs, idxGprArgs, puStackArgs); break;
+                case nsXPTType::T_I32:      fetchGpr(&paParams[i].val.i32, pauGprArgs, idxGprArgs, puStackArgs); break;
+                case nsXPTType::T_I64:      fetchGpr(&paParams[i].val.i64, pauGprArgs, idxGprArgs, puStackArgs); break;
+                case nsXPTType::T_U8:       fetchGpr(&paParams[i].val.u8,  pauGprArgs, idxGprArgs, puStackArgs); break;
+                case nsXPTType::T_U16:      fetchGpr(&paParams[i].val.u16, pauGprArgs, idxGprArgs, puStackArgs); break;
+                case nsXPTType::T_U32:      fetchGpr(&paParams[i].val.u32, pauGprArgs, idxGprArgs, puStackArgs); break;
+                case nsXPTType::T_U64:      fetchGpr(&paParams[i].val.u64, pauGprArgs, idxGprArgs, puStackArgs); break;
+                case nsXPTType::T_BOOL:     fetchGpr(&paParams[i].val.b,   pauGprArgs, idxGprArgs, puStackArgs); break;
+                case nsXPTType::T_CHAR:     fetchGpr(&paParams[i].val.c,   pauGprArgs, idxGprArgs, puStackArgs); break;
+                case nsXPTType::T_WCHAR:    fetchGpr(&paParams[i].val.wc,  pauGprArgs, idxGprArgs, puStackArgs); break;
+
+                case nsXPTType::T_FLOAT:    fetchFpr(&paParams[i].val.f,   pauFprArgs, idxFprArgs, puStackArgs); break;
+                case nsXPTType::T_DOUBLE:   fetchFpr(&paParams[i].val.d,   pauFprArgs, idxFprArgs, puStackArgs); break;
+
+                default:
+                    if (!Type.IsArithmetic())
+                        fetchGpr(&paParams[i].val.p, pauGprArgs, idxGprArgs, puStackArgs);
+                    else
+                        AssertMsgFailedReturn(("%#x idxMethod=%#x\n",(unsigned)Type, idxMethod), NS_ERROR_UNEXPECTED);
+                    break;
+            }
+        }
+    }
+
+    /*
+     * Dispatch the method call.
+     */
+    hrc = pThis->CallMethod((PRUint16)idxMethod, pMethodInfo, paParams);
+
+    NS_RELEASE(pInterfaceInfo);
+    return hrc;
+
+}
+
+#if 0
+extern "C" nsresult CommonXPTCStubTest(uint64_t x0,
+                                       uint64_t x1,
+                                       uint64_t x2,
+                                       uint64_t x3,
+                                       uint64_t x4,
+                                       uint64_t x5,
+                                       uint64_t x6,
+                                       uint64_t x7)
+{
+    uint64_t aGprs[8];
+    aGprs[0] = x0;
+    aGprs[1] = x1;
+    aGprs[2] = x2;
+    aGprs[3] = x3;
+    aGprs[4] = x4;
+    aGprs[5] = x5;
+    aGprs[6] = x6;
+    aGprs[7] = x7;
+
+    return CommonXPTCStubCWorker((nsXPTCStubBase *)x0, x1, aGprs, aGprs, aGprs);
+}
+#endif
+
