summaryrefslogtreecommitdiffstats
path: root/xpcom/reflect
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--xpcom/reflect/moz.build7
-rw-r--r--xpcom/reflect/xptcall/README6
-rw-r--r--xpcom/reflect/xptcall/genstubs.pl87
-rw-r--r--xpcom/reflect/xptcall/md/moz.build12
-rw-r--r--xpcom/reflect/xptcall/md/test/README6
-rwxr-xr-xxpcom/reflect/xptcall/md/test/clean.bat5
-rw-r--r--xpcom/reflect/xptcall/md/test/invoke_test.cpp187
-rwxr-xr-xxpcom/reflect/xptcall/md/test/mk_invoke.bat9
-rwxr-xr-xxpcom/reflect/xptcall/md/test/mk_stub.bat9
-rw-r--r--xpcom/reflect/xptcall/md/test/moz.build11
-rw-r--r--xpcom/reflect/xptcall/md/test/stub_test.cpp209
-rw-r--r--xpcom/reflect/xptcall/md/unix/moz.build282
-rw-r--r--xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp66
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h16
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp168
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp144
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp417
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp181
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp183
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.S92
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s145
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s146
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_loongarch64.S92
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S134
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S121
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s131
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s108
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S167
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s129
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s128
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s124
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S98
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S94
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s142
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_riscv64.S89
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s86
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s53
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s55
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s55
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_64_unix.S117
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp18
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp97
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp129
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp99
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp144
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp194
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp189
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp100
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp99
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp144
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp148
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp140
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp73
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp62
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp128
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp109
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp113
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_riscv64.cpp106
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp69
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp130
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp127
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp130
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp76
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp238
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp178
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp226
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp99
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp194
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.S62
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s123
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s124
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_loongarch64.S52
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S116
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m475
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S111
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s68
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s73
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S112
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4119
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m497
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4114
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S77
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S72
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_riscv64.S53
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s50
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s49
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s49
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s49
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp18
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp132
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp139
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp142
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp179
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp178
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp182
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_loongarch64.cpp159
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp104
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp183
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp141
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp280
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp181
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp168
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp211
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp194
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp150
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_riscv64.cpp160
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp101
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp103
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp103
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp104
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp183
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp209
-rw-r--r--xpcom/reflect/xptcall/md/win32/moz.build53
-rw-r--r--xpcom/reflect/xptcall/md/win32/preprocess.py44
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp45
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke_aarch64.cpp141
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_aarch64.asm66
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm107
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s110
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm63
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp58
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp106
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs.cpp133
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs_aarch64.cpp186
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs_asm_aarch64.asm306
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm335
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp188
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp297
-rw-r--r--xpcom/reflect/xptcall/moz.build20
-rw-r--r--xpcom/reflect/xptcall/nsXPTCUtils.h41
-rw-r--r--xpcom/reflect/xptcall/porting.html237
-rw-r--r--xpcom/reflect/xptcall/xptcall.cpp55
-rw-r--r--xpcom/reflect/xptcall/xptcall.h173
-rw-r--r--xpcom/reflect/xptcall/xptcprivate.h68
-rw-r--r--xpcom/reflect/xptcall/xptcstubsdecl.inc761
-rw-r--r--xpcom/reflect/xptcall/xptcstubsdef.inc252
-rw-r--r--xpcom/reflect/xptinfo/moz.build21
-rw-r--r--xpcom/reflect/xptinfo/xptcodegen.py646
-rw-r--r--xpcom/reflect/xptinfo/xptinfo.cpp105
-rw-r--r--xpcom/reflect/xptinfo/xptinfo.h711
140 files changed, 18547 insertions, 0 deletions
diff --git a/xpcom/reflect/moz.build b/xpcom/reflect/moz.build
new file mode 100644
index 0000000000..fca3fa4499
--- /dev/null
+++ b/xpcom/reflect/moz.build
@@ -0,0 +1,7 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DIRS += ["xptinfo", "xptcall"]
diff --git a/xpcom/reflect/xptcall/README b/xpcom/reflect/xptcall/README
new file mode 100644
index 0000000000..0c401fe88d
--- /dev/null
+++ b/xpcom/reflect/xptcall/README
@@ -0,0 +1,6 @@
+see:
+
+http://www.mozilla.org/scriptable/xptcall-faq.html
+and
+http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html
+
diff --git a/xpcom/reflect/xptcall/genstubs.pl b/xpcom/reflect/xptcall/genstubs.pl
new file mode 100644
index 0000000000..29797ccc58
--- /dev/null
+++ b/xpcom/reflect/xptcall/genstubs.pl
@@ -0,0 +1,87 @@
+#!/usr/local/bin/perl
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+# This is used to generate stub entry points. We generate a file to
+# be included in the declaraion and a file to be used for expanding macros
+# to represent the implementation of the stubs.
+
+#
+# if "$entry_count" is ever changed and the .inc files regenerated then
+# the following issues need to be addressed:
+#
+# 1) The current Linux ARM code has a limitation of only having 256-3 stubs,
+# as a result of the limitations of immediate values in ARM assembly.
+#
+# This number is verified by the IDL parser in xpcom/idl-parser/xpidl.py, as
+# well as in xpcom/reflect/xptinfo/xptinfo.cpp, to prevent generating interfaces
+# or loading xpt files that would cause the stubs to run off the entries.
+# If you change this number, please update that location.
+
+# 3 entries are already 'used' by the 3 methods of nsISupports.
+# 3+247+5=255 This should get us in under the Linux ARM limitation
+$entry_count = 247;
+$sentinel_count = 5;
+
+$decl_name = "xptcstubsdecl.inc";
+$def_name = "xptcstubsdef.inc";
+
+##
+## Write the declarations include file
+##
+
+die "Can't open $decl_name" if !open(OUTFILE, ">$decl_name");
+
+print OUTFILE "/* generated file - DO NOT EDIT */\n\n";
+print OUTFILE "/* includes ",$entry_count," stub entries, and ",
+ $sentinel_count," sentinel entries */\n\n";
+print OUTFILE "/*\n";
+print OUTFILE "* declarations of normal stubs...\n";
+print OUTFILE "* 0 is QueryInterface\n";
+print OUTFILE "* 1 is AddRef\n";
+print OUTFILE "* 2 is Release\n";
+print OUTFILE "*/\n";
+print OUTFILE "#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__))\n";
+for($i = 0; $i < $entry_count; $i++) {
+ print OUTFILE "NS_IMETHOD Stub",$i+3,"();\n";
+}
+print OUTFILE "#else\n";
+for($i = 0; $i < $entry_count; $i++) {
+ print OUTFILE "NS_IMETHOD Stub",$i+3,"(uint64_t,uint64_t,\n";
+ print OUTFILE " uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);\n";
+
+}
+print OUTFILE "#endif\n";
+
+print OUTFILE "\n/* declarations of sentinel stubs */\n";
+
+for($i = 0; $i < $sentinel_count; $i++) {
+ print OUTFILE "NS_IMETHOD Sentinel",$i,"();\n";
+}
+close(OUTFILE);
+
+
+##
+## Write the definitions include file. This assumes a macro will be used to
+## expand the entries written...
+##
+
+die "Can't open $def_name" if !open(OUTFILE, ">$def_name");
+
+## Disabled for bug 275004 - followup to fix is Bug 419604
+my $warn_inc_is_generated = 0;
+if ($warn_inc_is_generated) {
+print OUTFILE "/* generated file - DO NOT EDIT */\n\n";
+print OUTFILE "/* includes ",$entry_count," stub entries, and ",
+ $sentinel_count," sentinel entries */\n\n";
+}
+
+for($i = 0; $i < $entry_count; $i++) {
+ print OUTFILE "STUB_ENTRY(",$i+3,")\n";
+}
+
+for($i = 0; $i < $sentinel_count; $i++) {
+ print OUTFILE "SENTINEL_ENTRY(",$i,")\n";
+}
diff --git a/xpcom/reflect/xptcall/md/moz.build b/xpcom/reflect/xptcall/md/moz.build
new file mode 100644
index 0000000000..fcf4dde72f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/moz.build
@@ -0,0 +1,12 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+arch = CONFIG["OS_ARCH"]
+
+if arch == "WINNT":
+ DIRS += ["win32"]
+else:
+ DIRS += ["unix"]
diff --git a/xpcom/reflect/xptcall/md/test/README b/xpcom/reflect/xptcall/md/test/README
new file mode 100644
index 0000000000..04850b2e01
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/README
@@ -0,0 +1,6 @@
+These are just simple test programs in which stripped down versions of the
+XPConnect invoke and stubs code can be built and tested as the code is brought
+up on various platforms. These probrams do not test the param sizing and copying
+functionality of the routines. However, they do supply a place where the lowest
+level assembly language code can be developed and debugged in the simplest of
+contexts before it is moved into the real routines. \ No newline at end of file
diff --git a/xpcom/reflect/xptcall/md/test/clean.bat b/xpcom/reflect/xptcall/md/test/clean.bat
new file mode 100755
index 0000000000..f320e222c9
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/clean.bat
@@ -0,0 +1,5 @@
+@echo off
+echo deleting intermediate files
+if exist *.obj del *.obj > NUL
+if exist *.ilk del *.ilk > NUL
+if exist *.pdb del *.pdb > NUL \ No newline at end of file
diff --git a/xpcom/reflect/xptcall/md/test/invoke_test.cpp b/xpcom/reflect/xptcall/md/test/invoke_test.cpp
new file mode 100644
index 0000000000..f23a9ccf15
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/invoke_test.cpp
@@ -0,0 +1,187 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <stdio.h>
+
+typedef unsigned nsresult;
+typedef unsigned uint32_t;
+typedef unsigned nsXPCVariant;
+
+#if defined(WIN32)
+# define NS_IMETHOD virtual nsresult __stdcall
+# define NS_IMETHODIMP nsresult __stdcall
+#else
+# define NS_IMETHOD virtual nsresult
+# define NS_IMETHODIMP nsresult
+#endif
+
+class base {
+ public:
+ NS_IMETHOD ignored() = 0;
+};
+
+class foo : public base {
+ public:
+ NS_IMETHOD callme1(int i, int j) = 0;
+ NS_IMETHOD callme2(int i, int j) = 0;
+ NS_IMETHOD callme3(int i, int j) = 0;
+};
+
+class bar : public foo {
+ public:
+ NS_IMETHOD ignored() override;
+ NS_IMETHOD callme1(int i, int j) override;
+ NS_IMETHOD callme2(int i, int j) override;
+ NS_IMETHOD callme3(int i, int j) override;
+};
+
+/*
+class baz : public base {
+public:
+ NS_IMETHOD ignored() override;
+ NS_IMETHOD callme1() override;
+ NS_IMETHOD callme2() override;
+ NS_IMETHOD callme3() override;
+ void setfoo(foo* f) {other = f;}
+
+ foo* other;
+};
+NS_IMETHODIMP baz::ignored(){return 0;}
+*/
+
+NS_IMETHODIMP bar::ignored() { return 0; }
+
+NS_IMETHODIMP bar::callme1(int i, int j) {
+ printf("called bar::callme1 with: %d %d\n", i, j);
+ return 5;
+}
+
+NS_IMETHODIMP bar::callme2(int i, int j) {
+ printf("called bar::callme2 with: %d %d\n", i, j);
+ return 5;
+}
+
+NS_IMETHODIMP bar::callme3(int i, int j) {
+ printf("called bar::callme3 with: %d %d\n", i, j);
+ return 5;
+}
+
+void docall(foo* f, int i, int j) { f->callme1(i, j); }
+
+/***************************************************************************/
+#if defined(WIN32)
+
+static uint32_t __stdcall invoke_count_words(uint32_t paramCount,
+ nsXPCVariant* s) {
+ return paramCount;
+}
+
+static void __stdcall invoke_copy_to_stack(uint32_t* d, uint32_t paramCount,
+ nsXPCVariant* s) {
+ for (uint32_t i = 0; i < paramCount; i++, d++, s++) {
+ *((uint32_t*)d) = *((uint32_t*)s);
+ }
+}
+
+static nsresult __stdcall DoInvoke(void* that, uint32_t index,
+ uint32_t paramCount, nsXPCVariant* params) {
+ __asm {
+ push params
+ push paramCount
+ call invoke_count_words // stdcall, result in eax
+ shl eax,2 // *= 4
+ sub esp,eax // make space for params
+ mov edx,esp
+ push params
+ push paramCount
+ push edx
+ call invoke_copy_to_stack // stdcall
+ mov ecx,that // instance in ecx
+ push ecx // push this
+ mov edx,[ecx] // vtable in edx
+ mov eax,index
+ shl eax,2 // *= 4
+ add edx,eax
+ call [edx] // stdcall, i.e. callee cleans up stack.
+ }
+}
+
+#else
+/***************************************************************************/
+// just Linux_x86 now. Add other later...
+
+static uint32_t invoke_count_words(uint32_t paramCount, nsXPCVariant* s) {
+ return paramCount;
+}
+
+static void invoke_copy_to_stack(uint32_t* d, uint32_t paramCount,
+ nsXPCVariant* s) {
+ for (uint32_t i = 0; i < paramCount; i++, d++, s++) {
+ *((uint32_t*)d) = *((uint32_t*)s);
+ }
+}
+
+static nsresult DoInvoke(void* that, uint32_t index, uint32_t paramCount,
+ nsXPCVariant* params) {
+ uint32_t result;
+ void* fn_count = invoke_count_words;
+ void* fn_copy = invoke_copy_to_stack;
+
+ __asm__ __volatile__(
+ "pushl %4\n\t"
+ "pushl %3\n\t"
+ "movl %5, %%eax\n\t"
+ "call *%%eax\n\t" /* count words */
+ "addl $0x8, %%esp\n\t"
+ "shl $2, %%eax\n\t" /* *= 4 */
+ "subl %%eax, %%esp\n\t" /* make room for params */
+ "movl %%esp, %%edx\n\t"
+ "pushl %4\n\t"
+ "pushl %3\n\t"
+ "pushl %%edx\n\t"
+ "movl %6, %%eax\n\t"
+ "call *%%eax\n\t" /* copy params */
+ "addl $0xc, %%esp\n\t"
+ "movl %1, %%ecx\n\t"
+ "pushl %%ecx\n\t"
+ "movl (%%ecx), %%edx\n\t"
+ "movl %2, %%eax\n\t" /* function index */
+ "shl $2, %%eax\n\t" /* *= 4 */
+ "addl $8, %%eax\n\t" /* += 8 */
+ "addl %%eax, %%edx\n\t"
+ "call *(%%edx)\n\t" /* safe to not cleanup esp */
+ "movl %%eax, %0"
+ : "=g"(result) /* %0 */
+ : "g"(that), /* %1 */
+ "g"(index), /* %2 */
+ "g"(paramCount), /* %3 */
+ "g"(params), /* %4 */
+ "g"(fn_count), /* %5 */
+ "g"(fn_copy) /* %6 */
+ : "ax", "cx", "dx", "memory");
+
+ return result;
+}
+
+#endif
+/***************************************************************************/
+
+int main() {
+ nsXPCVariant params1[2] = {1, 2};
+ nsXPCVariant params2[2] = {2, 4};
+ nsXPCVariant params3[2] = {3, 6};
+
+ foo* a = new bar();
+
+ // printf("calling via C++...\n");
+ // docall(a, 12, 24);
+
+ printf("calling via ASM...\n");
+ DoInvoke(a, 1, 2, params1);
+ DoInvoke(a, 2, 2, params2);
+ DoInvoke(a, 3, 2, params3);
+
+ return 0;
+}
diff --git a/xpcom/reflect/xptcall/md/test/mk_invoke.bat b/xpcom/reflect/xptcall/md/test/mk_invoke.bat
new file mode 100755
index 0000000000..10a9be51de
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/mk_invoke.bat
@@ -0,0 +1,9 @@
+@echo off
+@echo deleing old output
+if exist invoke_test.obj del invoke_test.obj > NUL
+if exist invoke_test.ilk del invoke_test.ilk > NUL
+if exist *.pdb del *.pdb > NUL
+if exist invoke_test.exe del invoke_test.exe > NUL
+
+@echo building...
+cl /nologo -Zi -DWIN32 invoke_test.cpp \ No newline at end of file
diff --git a/xpcom/reflect/xptcall/md/test/mk_stub.bat b/xpcom/reflect/xptcall/md/test/mk_stub.bat
new file mode 100755
index 0000000000..f9af17affe
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/mk_stub.bat
@@ -0,0 +1,9 @@
+@echo off
+@echo deleing old output
+if exist stub_test.obj del stub_test.obj > NUL
+if exist stub_test.ilk del stub_test.ilk > NUL
+if exist *.pdb del *.pdb > NUL
+if exist stub_test.exe del stub_test.exe > NUL
+
+@echo building...
+cl /nologo -Zi -DWIN32 stub_test.cpp \ No newline at end of file
diff --git a/xpcom/reflect/xptcall/md/test/moz.build b/xpcom/reflect/xptcall/md/test/moz.build
new file mode 100644
index 0000000000..f31bcf64a3
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/moz.build
@@ -0,0 +1,11 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+SimplePrograms(
+ [
+ "stub_test",
+ ]
+)
diff --git a/xpcom/reflect/xptcall/md/test/stub_test.cpp b/xpcom/reflect/xptcall/md/test/stub_test.cpp
new file mode 100644
index 0000000000..c83eb93ccc
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/stub_test.cpp
@@ -0,0 +1,209 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <stdio.h>
+
+typedef unsigned nsresult;
+typedef unsigned uint32_t;
+typedef unsigned nsXPCVariant;
+
+#if defined(WIN32)
+# define NS_IMETHOD virtual nsresult __stdcall
+# define NS_IMETHODIMP nsresult __stdcall
+#else
+# define NS_IMETHOD virtual nsresult
+# define NS_IMETHODIMP nsresult
+#endif
+
+class base {
+ public:
+ NS_IMETHOD ignored() = 0;
+};
+
+class foo : public base {
+ public:
+ NS_IMETHOD callme1(int i, int j) = 0;
+ NS_IMETHOD callme2(int i, int j) = 0;
+ NS_IMETHOD callme3(int i, int j) = 0;
+};
+
+class bar : public foo {
+ public:
+ NS_IMETHOD ignored() override;
+ NS_IMETHOD callme1(int i, int j) override;
+ NS_IMETHOD callme2(int i, int j) override;
+ NS_IMETHOD callme3(int i, int j) override;
+};
+
+class baz : public base {
+ public:
+ NS_IMETHOD ignored() override;
+ NS_IMETHOD callme1() override;
+ NS_IMETHOD callme2() override;
+ NS_IMETHOD callme3() override;
+ void setfoo(foo* f) { other = f; }
+
+ foo* other;
+};
+NS_IMETHODIMP baz::ignored() { return 0; }
+
+NS_IMETHODIMP bar::ignored() { return 0; }
+
+NS_IMETHODIMP bar::callme1(int i, int j) {
+ printf("called bar::callme1 with: %d %d\n", i, j);
+ return 15;
+}
+
+NS_IMETHODIMP bar::callme2(int i, int j) {
+ printf("called bar::callme2 with: %d %d\n", i, j);
+ return 25;
+}
+
+NS_IMETHODIMP bar::callme3(int i, int j) {
+ printf("called bar::callme3 with: %d %d\n", i, j);
+ return 35;
+}
+
+void docall(foo* f, int i, int j) { f->callme1(i, j); }
+
+/***************************************************************************/
+#if defined(WIN32)
+
+static int __stdcall PrepareAndDispatch(baz* self, uint32_t methodIndex,
+ uint32_t* args,
+ uint32_t* stackBytesToPop) {
+ fprintf(stdout, "PrepareAndDispatch (%p, %d, %p)\n", (void*)self, methodIndex,
+ (void*)args);
+ foo* a = self->other;
+ int p1 = (int)*args;
+ int p2 = (int)*(args + 1);
+ int out = 0;
+ switch (methodIndex) {
+ case 1:
+ out = a->callme1(p1, p2);
+ break;
+ case 2:
+ out = a->callme2(p1, p2);
+ break;
+ case 3:
+ out = a->callme3(p1, p2);
+ break;
+ }
+ *stackBytesToPop = 2 * 4;
+ return out;
+}
+
+# ifndef __GNUC__
+static __declspec(naked) void SharedStub(void) {
+ __asm {
+ push ebp // set up simple stack frame
+ mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args
+ push ecx // make room for a ptr
+ lea eax, [ebp-4] // pointer to stackBytesToPop
+ push eax
+ lea ecx, [ebp+16] // pointer to args
+ push ecx
+ mov edx, [ebp+4] // vtbl_index
+ push edx
+ mov eax, [ebp+12] // this
+ push eax
+ call PrepareAndDispatch
+ mov edx, [ebp+8] // return address
+ mov ecx, [ebp-4] // stackBytesToPop
+ add ecx, 12 // for this, the index, and ret address
+ mov esp, ebp
+ pop ebp
+ add esp, ecx // fix up stack pointer
+ jmp edx // simulate __stdcall return
+ }
+}
+
+// these macros get expanded (many times) in the file #included below
+# define STUB_ENTRY(n) \
+ __declspec(naked) nsresult __stdcall baz::callme##n() { \
+ __asm push n __asm jmp SharedStub \
+ }
+
+# else /* __GNUC__ */
+
+# define STUB_ENTRY(n) \
+ nsresult __stdcall baz::callme##n() { \
+ uint32_t *args, stackBytesToPop; \
+ int result = 0; \
+ baz* obj; \
+ __asm__ __volatile__( \
+ "leal 0x0c(%%ebp), %0\n\t" /* args */ \
+ "movl 0x08(%%ebp), %1\n\t" /* this */ \
+ : "=r"(args), "=r"(obj)); \
+ result = PrepareAndDispatch(obj, n, args, &stackBytesToPop); \
+ fprintf(stdout, "stub returning: %d\n", result); \
+ fprintf(stdout, "bytes to pop: %d\n", stackBytesToPop); \
+ return result; \
+ }
+
+# endif /* ! __GNUC__ */
+
+#else
+/***************************************************************************/
+// just Linux_x86 now. Add other later...
+
+static int PrepareAndDispatch(baz* self, uint32_t methodIndex, uint32_t* args) {
+ foo* a = self->other;
+ int p1 = (int)*args;
+ int p2 = (int)*(args + 1);
+ switch (methodIndex) {
+ case 1:
+ a->callme1(p1, p2);
+ break;
+ case 2:
+ a->callme2(p1, p2);
+ break;
+ case 3:
+ a->callme3(p1, p2);
+ break;
+ }
+ return 1;
+}
+
+# define STUB_ENTRY(n) \
+ nsresult baz::callme##n() { \
+ void* method = PrepareAndDispatch; \
+ nsresult result; \
+ __asm__ __volatile__( \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "pushl %%ecx\n\t" \
+ "pushl $" #n \
+ "\n\t" /* method index */ \
+ "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \
+ "pushl %%ecx\n\t" \
+ "call *%%edx" /* PrepareAndDispatch */ \
+ : "=a"(result) /* %0 */ \
+ : "d"(method) /* %1 */ \
+ : "memory"); \
+ return result; \
+ }
+
+#endif
+/***************************************************************************/
+
+STUB_ENTRY(1)
+STUB_ENTRY(2)
+STUB_ENTRY(3)
+
+int main() {
+ foo* a = new bar();
+ baz* b = new baz();
+
+ /* here we make the global 'check for alloc failure' checker happy */
+ if (!a || !b) return 1;
+
+ foo* c = (foo*)b;
+
+ b->setfoo(a);
+ c->callme1(1, 2);
+ c->callme2(2, 4);
+ c->callme3(3, 6);
+
+ return 0;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/moz.build b/xpcom/reflect/xptcall/md/unix/moz.build
new file mode 100644
index 0000000000..e462ad0938
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/moz.build
@@ -0,0 +1,282 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+if CONFIG["OS_ARCH"] == "Darwin":
+ SOURCES += [
+ "xptcinvoke_darwin.cpp",
+ "xptcstubs_darwin.cpp",
+ ]
+ if CONFIG["TARGET_CPU"] == "ppc":
+ SOURCES += [
+ "!xptcstubs_asm_ppc_darwin.s",
+ "xptcinvoke_asm_ppc_rhapsody.s",
+ ]
+ if CONFIG["TARGET_CPU"] == "x86_64":
+ SOURCES += [
+ "xptcinvoke_asm_x86_64_unix.S",
+ ]
+ if CONFIG["TARGET_CPU"] == "aarch64":
+ SOURCES += [
+ "xptcinvoke_asm_aarch64.S",
+ "xptcstubs_asm_aarch64.S",
+ ]
+
+if CONFIG["OS_ARCH"] == "GNU":
+ if CONFIG["TARGET_CPU"] == "x86":
+ SOURCES += ["xptcinvoke_gcc_x86_unix.cpp", "xptcstubs_gcc_x86_unix.cpp"]
+
+if CONFIG["OS_ARCH"] in (
+ "Linux",
+ "Bitrig",
+ "DragonFly",
+ "FreeBSD",
+ "NetBSD",
+ "OpenBSD",
+ "SunOS",
+) or CONFIG["OS_ARCH"].startswith("GNU_"):
+ if CONFIG["TARGET_CPU"] == "x86_64":
+ SOURCES += [
+ "xptcinvoke_asm_x86_64_unix.S",
+ "xptcinvoke_x86_64_unix.cpp",
+ "xptcstubs_x86_64_linux.cpp",
+ ]
+ elif CONFIG["TARGET_CPU"] == "x86":
+ SOURCES += ["xptcinvoke_gcc_x86_unix.cpp", "xptcstubs_gcc_x86_unix.cpp"]
+
+if CONFIG["OS_ARCH"] in ("Linux", "FreeBSD"):
+ if CONFIG["TARGET_CPU"] == "ia64":
+ SOURCES += [
+ "xptcinvoke_asm_ipf64.s",
+ "xptcinvoke_ipf64.cpp",
+ "xptcstubs_asm_ipf64.s",
+ "xptcstubs_ipf64.cpp",
+ ]
+
+if CONFIG["TARGET_CPU"] == "Alpha":
+ if CONFIG["OS_ARCH"] in ("Linux", "FreeBSD", "NetBSD"):
+ SOURCES += [
+ "xptcinvoke_linux_alpha.cpp",
+ "xptcstubs_linux_alpha.cpp",
+ ]
+ elif CONFIG["OS_ARCH"] == "OpenBSD":
+ SOURCES += [
+ "xptcinvoke_alpha_openbsd.cpp",
+ "xptcstubs_alpha_openbsd.cpp",
+ ]
+
+if CONFIG["TARGET_CPU"] == "arm":
+ if CONFIG["OS_ARCH"] == "Linux":
+ SOURCES += ["xptcinvoke_arm.cpp", "xptcstubs_arm.cpp"]
+ CXXFLAGS += ["-O2"]
+ elif CONFIG["OS_ARCH"] == "NetBSD":
+ SOURCES += [
+ "xptcinvoke_arm_netbsd.cpp",
+ "xptcstubs_arm_netbsd.cpp",
+ ]
+
+if CONFIG["TARGET_CPU"] == "arm" and CONFIG["OS_ARCH"] in ("Bitrig", "OpenBSD"):
+ SOURCES += [
+ "xptcinvoke_arm_openbsd.cpp",
+ "xptcstubs_arm_openbsd.cpp",
+ ]
+
+if CONFIG["OS_ARCH"] == "HP-UX":
+ if CONFIG["CC"] != "gcc":
+ if CONFIG["TARGET_CPU"] == "ia64":
+ SOURCES += [
+ "xptcinvoke_asm_ipf32.s",
+ "xptcinvoke_ipf32.cpp",
+ "xptcstubs_asm_ipf32.s",
+ "xptcstubs_ipf32.cpp",
+ ]
+ else:
+ SOURCES += [
+ "xptcinvoke_asm_pa32.s",
+ "xptcinvoke_pa32.cpp",
+ "xptcstubs_asm_pa32.s",
+ "xptcstubs_pa32.cpp",
+ ]
+
+if CONFIG["OS_ARCH"] == "Linux":
+ if CONFIG["TARGET_CPU"] == "hppa":
+ if CONFIG["CC_TYPE"] in ("clang", "gcc"):
+ SOURCES += [
+ "xptcinvoke_asm_parisc_linux.s",
+ "xptcinvoke_pa32.cpp",
+ "xptcstubs_asm_parisc_linux.s",
+ "xptcstubs_pa32.cpp",
+ ]
+ elif CONFIG["COMPILE_ENVIRONMENT"]:
+ error("Unknown C++ compiler, xptcall assembly will probably be incorrect.")
+
+if CONFIG["OS_ARCH"] in ("Linux", "FreeBSD", "NetBSD", "OpenBSD"):
+ if CONFIG["TARGET_CPU"] == "aarch64":
+ SOURCES += [
+ "xptcinvoke_aarch64.cpp",
+ "xptcinvoke_asm_aarch64.S",
+ "xptcstubs_aarch64.cpp",
+ "xptcstubs_asm_aarch64.S",
+ ]
+ if CONFIG["TARGET_CPU"] == "mips64":
+ SOURCES += [
+ "xptcinvoke_asm_mips64.S",
+ "xptcinvoke_mips64.cpp",
+ "xptcstubs_asm_mips64.S",
+ "xptcstubs_mips64.cpp",
+ ]
+ if CONFIG["CC_TYPE"] == "clang":
+ ASFLAGS += [
+ "-fno-integrated-as",
+ ]
+ if CONFIG["TARGET_CPU"] == "mips32":
+ SOURCES += [
+ "xptcinvoke_asm_mips.S",
+ "xptcinvoke_mips.cpp",
+ "xptcstubs_asm_mips.S",
+ "xptcstubs_mips.cpp",
+ ]
+ if CONFIG["CC_TYPE"] == "clang":
+ ASFLAGS += [
+ "-fno-integrated-as",
+ ]
+
+if CONFIG["OS_ARCH"] == "AIX":
+ if CONFIG["HAVE_64BIT_BUILD"]:
+ SOURCES += [
+ "!xptcstubs_asm_ppc_aix64.s",
+ "xptcinvoke_asm_ppc_aix64.s",
+ "xptcinvoke_ppc_aix64.cpp",
+ "xptcstubs_ppc_aix64.cpp",
+ ]
+ else:
+ SOURCES += [
+ "!xptcstubs_asm_ppc_aix.s",
+ "xptcinvoke_ppc_aix.cpp",
+ "xptcstubs_ppc_aix.cpp",
+ ]
+ if CONFIG["AIX_OBJMODEL"] == "ibm":
+ SOURCES += [
+ "xptcinvoke_asm_ppc_ibmobj_aix.s",
+ ]
+ else:
+ SOURCES += [
+ "xptcinvoke_asm_ppc_aix.s",
+ ]
+
+if CONFIG["TARGET_CPU"] == "ppc":
+ if CONFIG["OS_ARCH"] in ("Linux", "FreeBSD"):
+ SOURCES += [
+ "xptcinvoke_asm_ppc_linux.S",
+ "xptcinvoke_ppc_linux.cpp",
+ "xptcstubs_asm_ppc_linux.S",
+ "xptcstubs_ppc_linux.cpp",
+ ]
+
+if CONFIG["TARGET_CPU"] == "ppc64":
+ if CONFIG["OS_ARCH"] in ("Linux", "FreeBSD"):
+ SOURCES += [
+ "xptcinvoke_asm_ppc64_linux.S",
+ "xptcinvoke_ppc64_linux.cpp",
+ "xptcstubs_asm_ppc64_linux.S",
+ "xptcstubs_ppc64_linux.cpp",
+ ]
+ if CONFIG["CC_TYPE"] == "clang":
+ ASFLAGS += [
+ "-fno-integrated-as",
+ ]
+
+if CONFIG["OS_ARCH"] == "OpenBSD" and CONFIG["TARGET_CPU"] == "ppc":
+ SOURCES += [
+ "xptcinvoke_asm_ppc_openbsd.S",
+ "xptcinvoke_ppc_openbsd.cpp",
+ "xptcstubs_asm_ppc_openbsd.S",
+ "xptcstubs_ppc_openbsd.cpp",
+ ]
+
+if CONFIG["OS_ARCH"] == "Linux" and CONFIG["TARGET_CPU"] == "sparc":
+ SOURCES += [
+ "xptcinvoke_asm_sparc_linux_GCC3.s",
+ "xptcinvoke_sparc_solaris.cpp",
+ "xptcstubs_asm_sparc_solaris.s",
+ "xptcstubs_sparc_solaris.cpp",
+ ]
+
+if CONFIG["OS_ARCH"] == "NetBSD" and CONFIG["TARGET_CPU"] == "sparc":
+ SOURCES += [
+ "xptcinvoke_asm_sparc_netbsd.s",
+ "xptcinvoke_sparc_netbsd.cpp",
+ "xptcstubs_asm_sparc_netbsd.s",
+ "xptcstubs_sparc_netbsd.cpp",
+ ]
+
+if CONFIG["OS_ARCH"] == "OpenBSD" and CONFIG["TARGET_CPU"] == "sparc":
+ SOURCES += [
+ "xptcinvoke_asm_sparc_openbsd.s",
+ "xptcinvoke_sparc_openbsd.cpp",
+ "xptcstubs_asm_sparc_openbsd.s",
+ "xptcstubs_sparc_openbsd.cpp",
+ ]
+
+if (
+ CONFIG["OS_ARCH"] in ("OpenBSD", "FreeBSD", "Linux", "SunOS")
+ and CONFIG["TARGET_CPU"] == "sparc64"
+):
+ SOURCES += [
+ "xptcinvoke_asm_sparc64_openbsd.s",
+ "xptcinvoke_sparc64_openbsd.cpp",
+ "xptcstubs_asm_sparc64_openbsd.s",
+ "xptcstubs_sparc64_openbsd.cpp",
+ ]
+
+if CONFIG["OS_ARCH"] == "Linux":
+ if CONFIG["TARGET_CPU"] == "s390":
+ SOURCES += [
+ "xptcinvoke_linux_s390.cpp",
+ "xptcstubs_linux_s390.cpp",
+ ]
+ CXXFLAGS += [
+ "-fno-strict-aliasing",
+ "-fno-inline",
+ "-fomit-frame-pointer",
+ "-mbackchain",
+ ]
+ elif CONFIG["TARGET_CPU"] == "s390x":
+ SOURCES += [
+ "xptcinvoke_linux_s390x.cpp",
+ "xptcstubs_linux_s390x.cpp",
+ ]
+ CXXFLAGS += [
+ "-fno-strict-aliasing",
+ "-fno-inline",
+ "-fomit-frame-pointer",
+ "-mbackchain",
+ ]
+ if CONFIG["CC_TYPE"] == "clang":
+ CXXFLAGS += [
+ "-fno-integrated-as",
+ ]
+
+if CONFIG["OS_ARCH"] in ("Linux", "OpenBSD") and CONFIG["TARGET_CPU"] == "riscv64":
+ SOURCES += [
+ "xptcinvoke_asm_riscv64.S",
+ "xptcinvoke_riscv64.cpp",
+ "xptcstubs_asm_riscv64.S",
+ "xptcstubs_riscv64.cpp",
+ ]
+
+if CONFIG["OS_ARCH"] == "Linux" and CONFIG["TARGET_CPU"] == "loongarch64":
+ SOURCES += [
+ "xptcinvoke_asm_loongarch64.S",
+ "xptcinvoke_loongarch64.cpp",
+ "xptcstubs_asm_loongarch64.S",
+ "xptcstubs_loongarch64.cpp",
+ ]
+
+FINAL_LIBRARY = "xul"
+
+LOCAL_INCLUDES += [
+ "../..",
+]
diff --git a/xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp b/xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp
new file mode 100644
index 0000000000..9139d4b2aa
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp
@@ -0,0 +1,66 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* this code contributed by Bert Driehuis <bert_driehuis@nl.compuware.com> */
+
+#include <stdio.h>
+
+// Try to determine the vtable layout generated by G++
+// Produces the offset at which the first vtable entry can be
+// found, and the factor to apply for subsequent entries on stdout.
+// Example output:
+// #define GCC_VTABLE_START 0xc
+// #define GCC_VTABLE_FACTOR 0x8
+
+class test {
+public:
+ virtual int t1(void);
+ virtual int t2(void);
+ int x;
+};
+
+test::test() { this->x = 0x12121212; };
+
+int test::t1(void) { return 1; }
+int test::t2(void) { return 2; }
+
+void die(char *x) {
+ fprintf(stderr, "%s\n", x);
+ exit(1);
+}
+
+int
+main()
+{
+ int i;
+ test *t = new test();
+ int *tp = (int *) t;
+ int off1 = -1;
+ int off2 = -1;
+ int factor;
+ int factorshift;
+
+ if (*tp++ != 0x12121212)
+ die("Integer element test::x not found!");
+ tp = (int *) *tp;
+ for (i = 0; i < 10; i++) {
+ if (tp[i] == (int) t->t1)
+ off1 = i;
+ if (tp[i] == (int) t->t2)
+ off2 = i;
+ }
+ if (off1 == -1 || off2 == -1)
+ die("Could not determine offset into vtable!");
+ factor = (off2 - off1) * 4;
+ factorshift = -1;
+ while (factor) {
+ factorshift++;
+ factor >>= 1;
+ }
+ printf("/* Automatically generated by vtable_layout_x86.cpp */\n");
+ printf("#define GCC_VTABLE_START\t0x%x\n", off1 * 4);
+ printf("#define GCC_VTABLE_FACTOR\t0x%x\n", (off2 - off1) * 4);
+ printf("#define GCC_VTABLE_SHIFT\t0x%x\n", factorshift);
+ exit(0);
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h b/xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h
new file mode 100644
index 0000000000..5d6e71c23c
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h
@@ -0,0 +1,16 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Special include file for xptc*_gcc_x86_unix.cpp */
+
+//
+// this may improve the static function calls, but may not.
+//
+
+#ifdef MOZ_NEED_LEADING_UNDERSCORE
+#define SYMBOL_UNDERSCORE "_"
+#else
+#define SYMBOL_UNDERSCORE
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp
new file mode 100644
index 0000000000..385cba17ad
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp
@@ -0,0 +1,168 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if !defined(__aarch64__)
+#error "This code is for Linux AArch64 only."
+#endif
+
+
+/* "Procedure Call Standard for the ARM 64-bit Architecture" document, sections
+ * "5.4 Parameter Passing" and "6.1.2 Procedure Calling" contain all the
+ * needed information.
+ *
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf
+ */
+
+#ifndef __AARCH64EL__
+#error "Only little endian compatibility was tested"
+#endif
+
+// The AAPCS doesn't require argument widening, but Apple's calling convention
+// does. If we are really fortunate, the compiler will clean up all the
+// copying for us.
+template<typename T>
+inline uint64_t normalize_arg(T value) {
+ return (uint64_t)value;
+}
+
+template<>
+inline uint64_t normalize_arg(float value) {
+ uint64_t result = 0;
+ memcpy(&result, &value, sizeof(value));
+ return result;
+}
+
+template<>
+inline uint64_t normalize_arg(double value) {
+ uint64_t result = 0;
+ memcpy(&result, &value, sizeof(value));
+ return result;
+}
+
+/*
+ * Allocation of function arguments to their appropriate place in registers
+ * if possible and then to the stack. Handling of 'that' argument which
+ * goes to register r0 is handled separately and does not belong here.
+ *
+ * Note that we are handling integer arguments and floating-point arguments
+ * identically, depending on which register area is passed to this function.
+ *
+ * 'reg_args' - pointer to the current position in the buffer,
+ * corresponding to the register arguments.
+ * 'reg_args_end' - pointer to the end of the registers argument
+ * buffer.
+ * 'stack_args' - pointer to the current position in the buffer,
+ * corresponding to the arguments on stack.
+ * 'data' - typed data to put on the stack.
+ */
+template<typename T>
+static inline void alloc_arg(uint64_t* &reg_args,
+ uint64_t* reg_args_end,
+ void* &stack_args,
+ T* data)
+{
+ if (reg_args < reg_args_end) {
+ *reg_args = normalize_arg(*data);
+ reg_args++;
+ } else {
+ // According to the ABI, types that are smaller than 8 bytes are
+ // passed in registers or 8-byte stack slots. This rule is only
+ // partially true on Apple platforms, where types smaller than 8
+ // bytes occupy only the space they require on the stack and
+ // their stack slot must be properly aligned.
+#ifdef __APPLE__
+ const size_t aligned_size = sizeof(T);
+#else
+ const size_t aligned_size = 8;
+#endif
+ // Ensure the pointer is aligned for the type
+ uintptr_t addr = (reinterpret_cast<uintptr_t>(stack_args) + aligned_size - 1) & ~(aligned_size - 1);
+ memcpy(reinterpret_cast<void*>(addr), data, sizeof(T));
+ // Point the stack to the next slot.
+ stack_args = reinterpret_cast<void*>(addr + aligned_size);
+ }
+}
+
+extern "C" void
+invoke_copy_to_stack(uint64_t* stk, uint64_t *end,
+ uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint64_t* ireg_args = stk;
+ uint64_t* ireg_end = ireg_args + 8;
+ // Pun on integer and floating-point registers being the same size.
+ uint64_t* freg_args = ireg_end;
+ uint64_t* freg_end = freg_args + 8;
+ void* stack_args = freg_end;
+
+ // leave room for 'that' argument in x0
+ ++ireg_args;
+
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (s->IsIndirect()) {
+ void* ptr = &s->val;
+ alloc_arg(ireg_args, ireg_end, stack_args, &ptr);
+ } else {
+ switch (s->type) {
+ case nsXPTType::T_FLOAT:
+ alloc_arg(freg_args, freg_end, stack_args, &s->val.f);
+ break;
+ case nsXPTType::T_DOUBLE:
+ alloc_arg(freg_args, freg_end, stack_args, &s->val.d);
+ break;
+ case nsXPTType::T_I8:
+ alloc_arg(ireg_args, ireg_end, stack_args, &s->val.i8);
+ break;
+ case nsXPTType::T_I16:
+ alloc_arg(ireg_args, ireg_end, stack_args, &s->val.i16);
+ break;
+ case nsXPTType::T_I32:
+ alloc_arg(ireg_args, ireg_end, stack_args, &s->val.i32);
+ break;
+ case nsXPTType::T_I64:
+ alloc_arg(ireg_args, ireg_end, stack_args, &s->val.i64);
+ break;
+ case nsXPTType::T_U8:
+ alloc_arg(ireg_args, ireg_end, stack_args, &s->val.u8);
+ break;
+ case nsXPTType::T_U16:
+ alloc_arg(ireg_args, ireg_end, stack_args, &s->val.u16);
+ break;
+ case nsXPTType::T_U32:
+ alloc_arg(ireg_args, ireg_end, stack_args, &s->val.u32);
+ break;
+ case nsXPTType::T_U64:
+ alloc_arg(ireg_args, ireg_end, stack_args, &s->val.u64);
+ break;
+ case nsXPTType::T_BOOL:
+ alloc_arg(ireg_args, ireg_end, stack_args, &s->val.b);
+ break;
+ case nsXPTType::T_CHAR:
+ alloc_arg(ireg_args, ireg_end, stack_args, &s->val.c);
+ break;
+ case nsXPTType::T_WCHAR:
+ alloc_arg(ireg_args, ireg_end, stack_args, &s->val.wc);
+ break;
+ default:
+ // all the others are plain pointer types
+ alloc_arg(ireg_args, ireg_end, stack_args, &s->val.p);
+ break;
+ }
+ }
+ }
+}
+
+extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ return _NS_InvokeByIndex(that, methodIndex, paramCount, params);
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp
new file mode 100644
index 0000000000..dc111e4358
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp
@@ -0,0 +1,144 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+/* Prototype specifies unmangled function name and disables unused warning */
+static void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+__asm__("invoke_copy_to_stack") __attribute__((used));
+
+static void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *d = (uint64_t)s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *d = (uint64_t)s->val.i8; break;
+ case nsXPTType::T_I16 : *d = (uint64_t)s->val.i16; break;
+ case nsXPTType::T_I32 : *d = (uint64_t)s->val.i32; break;
+ case nsXPTType::T_I64 : *d = (uint64_t)s->val.i64; break;
+ case nsXPTType::T_U8 : *d = (uint64_t)s->val.u8; break;
+ case nsXPTType::T_U16 : *d = (uint64_t)s->val.u16; break;
+ case nsXPTType::T_U32 : *d = (uint64_t)s->val.u32; break;
+ case nsXPTType::T_U64 : *d = (uint64_t)s->val.u64; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // convert floats to doubles if they are to be passed
+ // via registers so we can just deal with doubles later
+ union { uint64_t u64; double d; } t;
+ t.d = (double)s->val.f;
+ *d = t.u64;
+ }
+ else
+ // otherwise copy to stack normally
+ *d = (uint64_t)s->val.u32;
+ break;
+ case nsXPTType::T_DOUBLE : *d = (uint64_t)s->val.u64; break;
+ case nsXPTType::T_BOOL : *d = (uint64_t)s->val.b; break;
+ case nsXPTType::T_CHAR : *d = (uint64_t)s->val.c; break;
+ case nsXPTType::T_WCHAR : *d = (uint64_t)s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *d = (uint64_t)s->val.p;
+ break;
+ }
+ }
+}
+
+/*
+ * EXPORT_XPCOM_API(nsresult)
+ * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ * uint32_t paramCount, nsXPTCVariant* params)
+ */
+__asm__(
+ "#### NS_InvokeByIndex ####\n"
+".text\n\t"
+ ".align 5\n\t"
+ ".globl NS_InvokeByIndex\n\t"
+ ".ent NS_InvokeByIndex\n"
+"NS_InvokeByIndex:\n\t"
+ ".frame $15,32,$26,0\n\t"
+ ".mask 0x4008000,-32\n\t"
+ "ldgp $29,0($27)\n"
+"$NS_InvokeByIndex..ng:\n\t"
+ "subq $30,32,$30\n\t"
+ "stq $26,0($30)\n\t"
+ "stq $15,8($30)\n\t"
+ "bis $30,$30,$15\n\t"
+ ".prologue 1\n\t"
+
+ /*
+ * Allocate enough stack space to hold the greater of 6 or "paramCount"+1
+ * parameters. (+1 for "this" pointer) Room for at least 6 parameters
+ * is required for storage of those passed via registers.
+ */
+
+ "bis $31,5,$2\n\t" /* count = MAX(5, "paramCount") */
+ "cmplt $2,$18,$1\n\t"
+ "cmovne $1,$18,$2\n\t"
+ "s8addq $2,16,$1\n\t" /* room for count+1 params (8 bytes each) */
+ "bic $1,15,$1\n\t" /* stack space is rounded up to 0 % 16 */
+ "subq $30,$1,$30\n\t"
+
+ "stq $16,0($30)\n\t" /* save "that" (as "this" pointer) */
+ "stq $17,16($15)\n\t" /* save "methodIndex" */
+
+ "addq $30,8,$16\n\t" /* pass stack pointer */
+ "bis $18,$18,$17\n\t" /* pass "paramCount" */
+ "bis $19,$19,$18\n\t" /* pass "params" */
+ "bsr $26,$invoke_copy_to_stack..ng\n\t" /* call invoke_copy_to_stack */
+
+ /*
+ * Copy the first 6 parameters to registers and remove from stack frame.
+ * Both the integer and floating point registers are set for each parameter
+ * except the first which is the "this" pointer. (integer only)
+ * The floating point registers are all set as doubles since the
+ * invoke_copy_to_stack function should have converted the floats.
+ */
+ "ldq $16,0($30)\n\t" /* integer registers */
+ "ldq $17,8($30)\n\t"
+ "ldq $18,16($30)\n\t"
+ "ldq $19,24($30)\n\t"
+ "ldq $20,32($30)\n\t"
+ "ldq $21,40($30)\n\t"
+ "ldt $f17,8($30)\n\t" /* floating point registers */
+ "ldt $f18,16($30)\n\t"
+ "ldt $f19,24($30)\n\t"
+ "ldt $f20,32($30)\n\t"
+ "ldt $f21,40($30)\n\t"
+
+ "addq $30,48,$30\n\t" /* remove params from stack */
+
+ /*
+ * Call the virtual function with the constructed stack frame.
+ */
+ "bis $16,$16,$1\n\t" /* load "this" */
+ "ldq $2,16($15)\n\t" /* load "methodIndex" */
+ "ldq $1,0($1)\n\t" /* load vtable */
+ "s8addq $2,$31,$2\n\t" /* vtable index = "methodIndex" * 8 */
+ "addq $1,$2,$1\n\t"
+ "ldq $27,0($1)\n\t" /* load address of function */
+ "jsr $26,($27),0\n\t" /* call virtual function */
+ "ldgp $29,0($26)\n\t"
+
+ "bis $15,$15,$30\n\t"
+ "ldq $26,0($30)\n\t"
+ "ldq $15,8($30)\n\t"
+ "addq $30,32,$30\n\t"
+ "ret $31,($26),1\n\t"
+ ".end NS_InvokeByIndex"
+ );
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp
new file mode 100644
index 0000000000..39a6b406f4
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp
@@ -0,0 +1,417 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#include "mozilla/Compiler.h"
+
+#if !defined(__arm__) || !(defined(LINUX) || defined(ANDROID) || defined(XP_IOS))
+#error "This code is for Linux/iOS ARM only. Check that it works on your system, too.\nBeware that this code is highly compiler dependent."
+#endif
+
+#if MOZ_IS_GCC
+#if defined(__ARM_EABI__) && !defined(__ARM_PCS_VFP) && !defined(__ARM_PCS)
+#error "Can't identify floating point calling conventions.\nPlease ensure that your toolchain defines __ARM_PCS or __ARM_PCS_VFP."
+#endif
+#endif
+
+#ifndef __ARM_PCS_VFP
+
+/* This function copies a 64-bits word from dw to the given pointer in
+ * a buffer delimited by start and end, possibly wrapping around the
+ * buffer boundaries, and/or properly aligning the data at 64-bits word
+ * boundaries (for EABI).
+ * start and end are both assumed to be 64-bits aligned.
+ * Returns a pointer to the second 32-bits word copied (to accomodate
+ * the invoke_copy_to_stack loop).
+ */
+static uint32_t *
+copy_double_word(uint32_t *start, uint32_t *current, uint32_t *end, uint64_t *dw)
+{
+#ifdef __ARM_EABI__
+ /* Aligning the pointer for EABI */
+ current = (uint32_t *)(((uint32_t)current + 7) & ~7);
+ /* Wrap when reaching the end of the buffer */
+ if (current == end) current = start;
+#else
+ /* On non-EABI, 64-bits values are not aligned and when we reach the end
+ * of the buffer, we need to write half of the data at the end, and the
+ * other half at the beginning. */
+ if (current == end - 1) {
+ *current = ((uint32_t*)dw)[0];
+ *start = ((uint32_t*)dw)[1];
+ return start;
+ }
+#endif
+
+ *((uint64_t*) current) = *dw;
+ return current + 1;
+}
+
+/* See stack_space comment in NS_InvokeByIndex to see why this needs not to
+ * be static on DEBUG builds. */
+#ifndef DEBUG
+static
+#endif
+void
+invoke_copy_to_stack(uint32_t* stk, uint32_t *end,
+ uint32_t paramCount, nsXPTCVariant* s)
+{
+ /* The stack buffer is 64-bits aligned. The end argument points to its end.
+ * The caller is assumed to create a stack buffer of at least four 32-bits
+ * words.
+ * We use the last three 32-bit words to store the values for r1, r2 and r3
+ * for the method call, i.e. the first words for arguments passing.
+ */
+ uint32_t *d = end - 3;
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ /* Wrap when reaching the end of the stack buffer */
+ if (d == end) d = stk;
+ NS_ASSERTION(d >= stk && d < end,
+ "invoke_copy_to_stack is copying outside its given buffer");
+ if(s->IsIndirect())
+ {
+ *((void**)d) = &s->val;
+ continue;
+ }
+ // According to the ARM EABI, integral types that are smaller than a word
+ // are to be sign/zero-extended to a full word and treated as 4-byte values.
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 :
+ d = copy_double_word(stk, d, end, (uint64_t *)&s->val.i64);
+ break;
+ case nsXPTType::T_U8 : *((uint32_t*)d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 :
+ d = copy_double_word(stk, d, end, (uint64_t *)&s->val.u64);
+ break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE :
+ d = copy_double_word(stk, d, end, (uint64_t *)&s->val.d);
+ break;
+ case nsXPTType::T_BOOL : *((int32_t*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((int32_t*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+typedef nsresult (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t);
+
+// Avoid AddressSanitizer instrumentation for the next function because it
+// depends on __builtin_alloca behavior and alignment that cannot be relied on
+// once the function is compiled with a version of ASan that has dynamic-alloca
+// instrumentation enabled.
+
+MOZ_ASAN_IGNORE
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+
+/* This is to call a given method of class that.
+ * The parameters are in params, the number is in paramCount.
+ * The routine will issue calls to count the number of words
+ * required for argument passing and to copy the arguments to
+ * the stack.
+ * ACPS passes the first 3 params in r1-r3 (with exceptions for 64-bits
+ * arguments), and the remaining goes onto the stack.
+ * We allocate a buffer on the stack for a "worst case" estimate of how much
+ * stack might be needed for EABI, i.e. twice the number of parameters.
+ * The end of this buffer will be used to store r1 to r3, so that the start
+ * of the stack is the remaining parameters.
+ * The magic here is to call the method with "that" and three 32-bits
+ * arguments corresponding to r1-r3, so that the compiler generates the
+ * proper function call. The stack will also contain the remaining arguments.
+ *
+ * !!! IMPORTANT !!!
+ * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented
+ * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])!
+ *
+ */
+
+ vtable_func *vtable, func;
+ int base_size = (paramCount > 1) ? paramCount : 2;
+
+/* !!! IMPORTANT !!!
+ * On DEBUG builds, the NS_ASSERTION used in invoke_copy_to_stack needs to use
+ * the stack to pass the 5th argument to NS_DebugBreak. When invoke_copy_to_stack
+ * is inlined, this can result, depending on the compiler and flags, in the
+ * stack pointer not pointing at stack_space when the method is called at the
+ * end of this function. More generally, any function call requiring stack
+ * allocation of arguments is unsafe to be inlined in this function.
+ */
+ uint32_t *stack_space = (uint32_t *) __builtin_alloca(base_size * 8);
+
+ invoke_copy_to_stack(stack_space, &stack_space[base_size * 2],
+ paramCount, params);
+
+ vtable = *reinterpret_cast<vtable_func **>(that);
+ func = vtable[methodIndex];
+
+ return func(that, stack_space[base_size * 2 - 3],
+ stack_space[base_size * 2 - 2],
+ stack_space[base_size * 2 - 1]);
+}
+
+#else /* __ARM_PCS_VFP */
+
+/* "Procedure Call Standard for the ARM Architecture" document, sections
+ * "5.5 Parameter Passing" and "6.1.2 Procedure Calling" contain all the
+ * needed information.
+ *
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf
+ */
+
+#if defined(__thumb__) && !defined(__thumb2__)
+#error "Thumb1 is not supported"
+#endif
+
+#ifndef __ARMEL__
+#error "Only little endian compatibility was tested"
+#endif
+
+/*
+ * Allocation of integer function arguments initially to registers r1-r3
+ * and then to stack. Handling of 'this' argument which goes to r0 registers
+ * is handled separately and does not belong to these two inline functions.
+ *
+ * The doubleword arguments are allocated to even:odd
+ * register pairs or get aligned at 8-byte boundary on stack. The "holes"
+ * which may appear as a result of this realignment remain unused.
+ *
+ * 'ireg_args' - pointer to the current position in the buffer,
+ * corresponding to the register arguments
+ * 'stack_args' - pointer to the current position in the buffer,
+ * corresponding to the arguments on stack
+ * 'end' - pointer to the end of the registers argument
+ * buffer (it is guaranteed to be 8-bytes aligned)
+ */
+
+static inline void copy_word(uint32_t* &ireg_args,
+ uint32_t* &stack_args,
+ uint32_t* end,
+ uint32_t data)
+{
+ if (ireg_args < end) {
+ *ireg_args = data;
+ ireg_args++;
+ } else {
+ *stack_args = data;
+ stack_args++;
+ }
+}
+
+static inline void copy_dword(uint32_t* &ireg_args,
+ uint32_t* &stack_args,
+ uint32_t* end,
+ uint64_t data)
+{
+ if (ireg_args + 1 < end) {
+ if ((uint32_t)ireg_args & 4) {
+ ireg_args++;
+ }
+ *(uint64_t *)ireg_args = data;
+ ireg_args += 2;
+ } else {
+ ireg_args = end;
+ if ((uint32_t)stack_args & 4) {
+ stack_args++;
+ }
+ *(uint64_t *)stack_args = data;
+ stack_args += 2;
+ }
+}
+
+/*
+ * Allocation of floating point arguments to VFP registers (s0-s15, d0-d7).
+ *
+ * Unlike integer registers allocation, "back-filling" needs to be
+ * supported. For example, the third floating point argument in the
+ * following function is going to be allocated to s1 register, back-filling
+ * the "hole":
+ * void f(float s0, double d1, float s1)
+ *
+ * Refer to the "Procedure Call Standard for the ARM Architecture" document
+ * for more details.
+ *
+ * 'vfp_s_args' - pointer to the current position in the buffer with
+ * the next unallocated single precision register
+ * 'vfp_d_args' - pointer to the current position in the buffer with
+ * the next unallocated double precision register,
+ * it has the same value as 'vfp_s_args' when back-filling
+ * is not used
+ * 'end' - pointer to the end of the vfp registers argument
+ * buffer (it is guaranteed to be 8-bytes aligned)
+ *
+ * Mozilla bugtracker has a test program attached which be used for
+ * experimenting with VFP registers allocation code and testing its
+ * correctness:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=601914#c19
+ */
+
+static inline bool copy_vfp_single(float* &vfp_s_args, double* &vfp_d_args,
+ float* end, float data)
+{
+ if (vfp_s_args >= end)
+ return false;
+
+ *vfp_s_args = data;
+ vfp_s_args++;
+ if (vfp_s_args < (float *)vfp_d_args) {
+ // It was the case of back-filling, now the next free single precision
+ // register should overlap with the next free double precision register
+ vfp_s_args = (float *)vfp_d_args;
+ } else if (vfp_s_args > (float *)vfp_d_args) {
+ // also update the pointer to the next free double precision register
+ vfp_d_args++;
+ }
+ return true;
+}
+
+static inline bool copy_vfp_double(float* &vfp_s_args, double* &vfp_d_args,
+ float* end, double data)
+{
+ if (vfp_d_args >= (double *)end) {
+ // The back-filling continues only so long as no VFP CPRC has been
+ // allocated to a slot on the stack. Basically no VFP registers can
+ // be allocated after this point.
+ vfp_s_args = end;
+ return false;
+ }
+
+ if (vfp_s_args == (float *)vfp_d_args) {
+ // also update the pointer to the next free single precision register
+ vfp_s_args += 2;
+ }
+ *vfp_d_args = data;
+ vfp_d_args++;
+ return true;
+}
+
+static void
+invoke_copy_to_stack(uint32_t* stk, uint32_t *end,
+ uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t *ireg_args = end - 3;
+ float *vfp_s_args = (float *)end;
+ double *vfp_d_args = (double *)end;
+ float *vfp_end = vfp_s_args + 16;
+
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (s->IsIndirect()) {
+ copy_word(ireg_args, stk, end, (uint32_t)&s->val);
+ continue;
+ }
+ // According to the ARM EABI, integral types that are smaller than a word
+ // are to be sign/zero-extended to a full word and treated as 4-byte values
+ switch (s->type)
+ {
+ case nsXPTType::T_FLOAT:
+ if (!copy_vfp_single(vfp_s_args, vfp_d_args, vfp_end, s->val.f)) {
+ copy_word(end, stk, end, reinterpret_cast<uint32_t&>(s->val.f));
+ }
+ break;
+ case nsXPTType::T_DOUBLE:
+ if (!copy_vfp_double(vfp_s_args, vfp_d_args, vfp_end, s->val.d)) {
+ copy_dword(end, stk, end, reinterpret_cast<uint64_t&>(s->val.d));
+ }
+ break;
+ case nsXPTType::T_I8: copy_word(ireg_args, stk, end, s->val.i8); break;
+ case nsXPTType::T_I16: copy_word(ireg_args, stk, end, s->val.i16); break;
+ case nsXPTType::T_I32: copy_word(ireg_args, stk, end, s->val.i32); break;
+ case nsXPTType::T_I64: copy_dword(ireg_args, stk, end, s->val.i64); break;
+ case nsXPTType::T_U8: copy_word(ireg_args, stk, end, s->val.u8); break;
+ case nsXPTType::T_U16: copy_word(ireg_args, stk, end, s->val.u16); break;
+ case nsXPTType::T_U32: copy_word(ireg_args, stk, end, s->val.u32); break;
+ case nsXPTType::T_U64: copy_dword(ireg_args, stk, end, s->val.u64); break;
+ case nsXPTType::T_BOOL: copy_word(ireg_args, stk, end, s->val.b); break;
+ case nsXPTType::T_CHAR: copy_word(ireg_args, stk, end, s->val.c); break;
+ case nsXPTType::T_WCHAR: copy_word(ireg_args, stk, end, s->val.wc); break;
+ default:
+ // all the others are plain pointer types
+ copy_word(ireg_args, stk, end, reinterpret_cast<uint32_t>(s->val.p));
+ break;
+ }
+ }
+}
+
+typedef uint32_t (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t);
+
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ vtable_func *vtable = *reinterpret_cast<vtable_func **>(that);
+ vtable_func func = vtable[methodIndex];
+ // 'register uint32_t result asm("r0")' could be used here, but it does not
+ // seem to be reliable in all cases: http://gcc.gnu.org/PR46164
+ nsresult result;
+ asm (
+ "mov r3, sp\n"
+ "mov %[stack_space_size], %[param_count_plus_2], lsl #3\n"
+ "tst r3, #4\n" /* check stack alignment */
+
+ "add %[stack_space_size], #(4 * 16)\n" /* space for VFP registers */
+ "mov r3, %[params]\n"
+
+ "it ne\n"
+ "addne %[stack_space_size], %[stack_space_size], #4\n"
+ "sub r0, sp, %[stack_space_size]\n" /* allocate space on stack */
+
+ "sub r2, %[param_count_plus_2], #2\n"
+ "mov sp, r0\n"
+
+ "add r1, r0, %[param_count_plus_2], lsl #3\n"
+ "blx %[invoke_copy_to_stack]\n"
+
+ "add ip, sp, %[param_count_plus_2], lsl #3\n"
+ "mov r0, %[that]\n"
+ "ldmdb ip, {r1, r2, r3}\n"
+ "vldm ip, {d0, d1, d2, d3, d4, d5, d6, d7}\n"
+ "blx %[func]\n"
+
+ "add sp, sp, %[stack_space_size]\n" /* cleanup stack */
+ "mov %[stack_space_size], r0\n" /* it's actually 'result' variable */
+ : [stack_space_size] "=&r" (result)
+ : [func] "r" (func),
+ [that] "r" (that),
+ [params] "r" (params),
+ [param_count_plus_2] "r" (paramCount + 2),
+ [invoke_copy_to_stack] "r" (invoke_copy_to_stack)
+ : "cc", "memory",
+ // Mark all the scratch registers as clobbered because they may be
+ // modified by the functions, called from this inline assembly block
+ "r0", "r1", "r2", "r3", "ip", "lr",
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ // Also unconditionally mark d16-d31 registers as clobbered even though
+ // they actually don't exist in vfpv2 and vfpv3-d16 variants. There is
+ // no way to identify VFP variant using preprocessor at the momemnt
+ // (see http://gcc.gnu.org/PR46128 for more details), but fortunately
+ // current versions of gcc do not seem to complain about these registers
+ // even when this code is compiled with '-mfpu=vfpv3-d16' option.
+ // If gcc becomes more strict in the future and/or provides a way to
+ // identify VFP variant, the following d16-d31 registers list needs
+ // to be wrapped into some #ifdef
+ "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
+ "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"
+ );
+ return result;
+}
+
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp
new file mode 100644
index 0000000000..2624c1e892
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp
@@ -0,0 +1,181 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+// Remember that these 'words' are 32bit DWORDS
+
+static uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t result = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+static void
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C"
+struct my_params_struct {
+ nsISupports* that;
+ uint32_t Index;
+ uint32_t Count;
+ nsXPTCVariant* params;
+ uint32_t fn_count;
+ uint32_t fn_copy;
+};
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ uint32_t result;
+ struct my_params_struct my_params;
+ my_params.that = that;
+ my_params.Index = methodIndex;
+ my_params.Count = paramCount;
+ my_params.params = params;
+ my_params.fn_copy = (uint32_t) &invoke_copy_to_stack;
+ my_params.fn_count = (uint32_t) &invoke_count_words;
+
+/* This is to call a given method of class that.
+ * The parameters are in params, the number is in paramCount.
+ * The routine will issue calls to count the number of words
+ * required for argument passing and to copy the arguments to
+ * the stack.
+ * Since APCS passes the first 3 params in r1-r3, we need to
+ * load the first three words from the stack and correct the stack
+ * pointer (sp) in the appropriate way. This means:
+ *
+ * 1.) more than 3 arguments: load r1-r3, correct sp and remember No.
+ * of bytes left on the stack in r4
+ *
+ * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope),
+ * restore sp as if nothing had happened and set the marker r4 to zero.
+ *
+ * Afterwards sp will be restored using the value in r4 (which is not a temporary register
+ * and will be preserved by the function/method called according to APCS [ARM Procedure
+ * Calling Standard]).
+ *
+ * !!! IMPORTANT !!!
+ * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented
+ * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])!
+ *
+ */
+
+ __asm__ __volatile__(
+ "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */
+ "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */
+ "ldr r0, [%1, #8] \n\t"
+ "mov lr, pc \n\t" /* call it... */
+ "mov pc, ip \n\t"
+ "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */
+ "sub sp, sp, r4 \n\t" /* use stack space for the args... */
+ "mov r0, sp \n\t" /* prepare a pointer an the stack */
+ "ldr r1, [%1, #8] \n\t" /* =paramCount */
+ "ldr r2, [%1, #12] \n\t" /* =params */
+ "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */
+ "mov lr, pc \n\t" /* copy args to the stack like the */
+ "mov pc, ip \n\t" /* compiler would. */
+ "ldr r0, [%1] \n\t" /* =that */
+ "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */
+ "ldr r2, [%1, #4] \n\t"
+ "add r2, r1, r2, lsl #3\n\t" /* a vtable_entry(x)=8 + (8 bytes * x) */
+ "add r2, r2, #8 \n\t" /* with this compilers */
+ "ldr r3, [r2] \n\t" /* get virtual offset from vtable */
+ "mov r3, r3, lsl #16 \n\t"
+ "add r0, r0, r3, asr #16\n\t"
+ "ldr ip, [r2, #4] \n\t" /* get method address from vtable */
+ "cmp r4, #12 \n\t" /* more than 3 arguments??? */
+ "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */
+ "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */
+ "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */
+ "addle sp, sp, r4 \n\t" /* and restore stack pointer */
+ "movle r4, #0 \n\t" /* a mark for restoring sp */
+ "mov lr, pc \n\t" /* call mathod */
+ "mov pc, ip \n\t"
+ "add sp, sp, r4 \n\t" /* restore stack pointer */
+ "mov %0, r0 \n\t" /* the result... */
+ : "=r" (result)
+ : "r" (&my_params)
+ : "r0", "r1", "r2", "r3", "r4", "ip", "lr"
+ );
+
+ return result;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp
new file mode 100644
index 0000000000..60b0574200
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp
@@ -0,0 +1,183 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+// Remember that these 'words' are 32bit DWORDS
+
+static uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t result = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+static void
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" {
+ struct my_params_struct {
+ nsISupports* that;
+ uint32_t Index;
+ uint32_t Count;
+ nsXPTCVariant* params;
+ uint32_t fn_count;
+ uint32_t fn_copy;
+ };
+}
+
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ uint32_t result;
+ struct my_params_struct my_params;
+ my_params.that = that;
+ my_params.Index = methodIndex;
+ my_params.Count = paramCount;
+ my_params.params = params;
+ my_params.fn_copy = (uint32_t) &invoke_copy_to_stack;
+ my_params.fn_count = (uint32_t) &invoke_count_words;
+
+/* This is to call a given method of class that.
+ * The parameters are in params, the number is in paramCount.
+ * The routine will issue calls to count the number of words
+ * required for argument passing and to copy the arguments to
+ * the stack.
+ * Since APCS passes the first 3 params in r1-r3, we need to
+ * load the first three words from the stack and correct the stack
+ * pointer (sp) in the appropriate way. This means:
+ *
+ * 1.) more than 3 arguments: load r1-r3, correct sp and remember No.
+ * of bytes left on the stack in r4
+ *
+ * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope),
+ * restore sp as if nothing had happened and set the marker r4 to zero.
+ *
+ * Afterwards sp will be restored using the value in r4 (which is not a temporary register
+ * and will be preserved by the function/method called according to APCS [ARM Procedure
+ * Calling Standard]).
+ *
+ * !!! IMPORTANT !!!
+ * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented
+ * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])!
+ *
+ */
+
+#ifdef __GNUC__
+ __asm__ __volatile__(
+ "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */
+ "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */
+ "ldr r0, [%1, #8] \n\t"
+ "mov lr, pc \n\t" /* call it... */
+ "mov pc, ip \n\t"
+ "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */
+ "sub sp, sp, r4 \n\t" /* use stack space for the args... */
+ "mov r0, sp \n\t" /* prepare a pointer an the stack */
+ "ldr r1, [%1, #8] \n\t" /* =paramCount */
+ "ldr r2, [%1, #12] \n\t" /* =params */
+ "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */
+ "mov lr, pc \n\t" /* copy args to the stack like the */
+ "mov pc, ip \n\t" /* compiler would. */
+ "ldr r0, [%1] \n\t" /* =that */
+ "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */
+ "ldr r2, [%1, #4] \n\t"
+ "mov r2, r2, lsl #2 \n\t" /* a vtable_entry(x)=8 + (4 bytes * x) */
+ "ldr ip, [r1, r2] \n\t" /* get method adress from vtable */
+ "cmp r4, #12 \n\t" /* more than 3 arguments??? */
+ "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */
+ "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */
+ "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */
+ "addle sp, sp, r4 \n\t" /* and restore stack pointer */
+ "movle r4, #0 \n\t" /* a mark for restoring sp */
+ "ldr r0, [%1, #0] \n\t" /* get (self) */
+ "mov lr, pc \n\t" /* call mathod */
+ "mov pc, ip \n\t"
+ "add sp, sp, r4 \n\t" /* restore stack pointer */
+ "mov %0, r0 \n\t" /* the result... */
+ : "=r" (result)
+ : "r" (&my_params), "m" (my_params)
+ : "r0", "r1", "r2", "r3", "r4", "ip", "lr", "sp"
+ );
+#else
+#error "Unsupported compiler. Use g++ >= 2.8 for OpenBSD/arm."
+#endif /* G++ >= 2.8 */
+
+ return result;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.S
new file mode 100644
index 0000000000..69a55b1c1c
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.S
@@ -0,0 +1,92 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifdef __APPLE__
+#define SYM(x) _ ## x
+#else
+#define SYM(x) x
+#endif
+
+ .text
+ .align 2
+ .globl SYM(_NS_InvokeByIndex)
+#ifndef __APPLE__
+ .type _NS_InvokeByIndex,@function
+#endif
+
+/*
+ * _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ * uint32_t paramCount, nsXPTCVariant* params)
+ */
+
+SYM(_NS_InvokeByIndex):
+ .cfi_startproc
+ # set up frame
+ stp x29, x30, [sp,#-32]!
+ .cfi_adjust_cfa_offset 32
+ .cfi_rel_offset x29, 0
+ .cfi_rel_offset x30, 8
+ mov x29, sp
+ .cfi_def_cfa_register x29
+ stp x19, x20, [sp,#16]
+ .cfi_rel_offset x19, 16
+ .cfi_rel_offset x20, 24
+
+ # save methodIndex across function calls
+ mov w20, w1
+
+ # end of stack area passed to invoke_copy_to_stack
+ mov x1, sp
+
+ # assume 8 bytes of stack for each argument with 16-byte alignment
+ add w19, w2, #1
+ and w19, w19, #0xfffffffe
+ sub sp, sp, w19, uxth #3
+
+ # temporary place to store args passed in r0-r7,v0-v7
+ sub sp, sp, #128
+
+ # save 'that' on stack
+ str x0, [sp]
+
+ # start of stack area passed to invoke_copy_to_stack
+ mov x0, sp
+ bl SYM(invoke_copy_to_stack)
+
+ # load arguments passed in r0-r7
+ ldp x6, x7, [sp, #48]
+ ldp x4, x5, [sp, #32]
+ ldp x2, x3, [sp, #16]
+ ldp x0, x1, [sp],#64
+
+ # load arguments passed in v0-v7
+ ldp d6, d7, [sp, #48]
+ ldp d4, d5, [sp, #32]
+ ldp d2, d3, [sp, #16]
+ ldp d0, d1, [sp],#64
+
+ # call the method
+ ldr x16, [x0]
+ add x16, x16, w20, uxth #3
+ ldr x16, [x16]
+ blr x16
+
+ add sp, sp, w19, uxth #3
+ .cfi_def_cfa_register sp
+ ldp x19, x20, [sp,#16]
+ .cfi_restore x19
+ .cfi_restore x20
+ ldp x29, x30, [sp],#32
+ .cfi_adjust_cfa_offset -32
+ .cfi_restore x29
+ .cfi_restore x30
+ ret
+ .cfi_endproc
+
+#ifndef __APPLE__
+ .size _NS_InvokeByIndex, . - _NS_InvokeByIndex
+
+ .section .note.GNU-stack, "", @progbits
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s
new file mode 100644
index 0000000000..794c4f5c17
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s
@@ -0,0 +1,145 @@
+
+// Select C numeric constant
+ .radix C
+// for 64 bit mode, use .psr abi64
+ .psr abi32
+// big endian
+ .psr msb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'NS_InvokeByIndex'
+ .proc NS_InvokeByIndex
+// manual bundling
+ .explicit
+
+// extern "C" uint32_t
+// invoke_copy_to_stack(uint64_t* d,
+// const uint32_t paramCount, nsXPTCVariant* s)
+ .global invoke_copy_to_stack
+// .exclass invoke_copy_to_stack, @fullyvisible
+ .type invoke_copy_to_stack,@function
+
+// .exclass NS_InvokeByIndex, @fullyvisible
+ .type NS_InvokeByIndex,@function
+
+// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+// uint32_t paramCount, nsXPTCVariant* params);
+NS_InvokeByIndex::
+ .prologue
+ .save ar.pfs, r37
+// allocate 4 input args, 6 local args, and 8 output args
+ alloc r37 = ar.pfs, 4, 6, 8, 0 // M
+ nop.i 0 ;; // I
+
+// unwind table already knows gp, no need to specify anything
+ add r39 = 0, gp // A
+ .save rp, r36
+ mov r36 = rp // I
+ .vframe r38
+ add r38 = 0, sp ;; // A
+
+// We first calculate the amount of extra memory stack space required
+// for the arguments, and register storage.
+// We then call invoke_copy_to_stack() to write the argument contents
+// to the specified memory regions.
+// We then copy the integer arguments to integer registers, and floating
+// arguments to float registers.
+// Lastly we load the virtual table jump pointer, and call the target
+// subroutine.
+
+// in0 : that
+// in1 : methodIndex
+// in2 : paramCount
+// in3 : params
+
+// stack frame size is 16 + (8 * even(paramCount)) + 64 + 64
+// 16 byte frame header
+// 8 * even(paramCount) memory argument area
+// 64 bytes integer register area
+// 64 bytes float register area
+// This scheme makes sure stack fram size is a multiple of 16
+
+ .body
+ add r10 = 8, r0 // A
+// r41 points to float register area
+ add r41 = -64, sp // A
+// r40 points to int register area
+ add r40 = -128, sp ;; // A
+
+ add out1 = 0, r40 // A
+ add out2 = 0, r41 // A
+ tbit.z p14,p15 = in2,0 ;; // I
+
+// compute 8 * even(paramCount)
+(p14) shladd r11 = in2, 3, r0 ;; // A
+(p15) shladd r11 = in2, 3, r10 ;; // A
+ sub out0 = r40, r11 ;; // A
+
+// advance the stack frame
+ add sp = -16, out0 // A
+ add out3 = 0, in2 // A
+ add out4 = 0, in3 // A
+
+// branch to invoke_copy_to_stack
+ br.call.sptk.few rp = invoke_copy_to_stack ;; // B
+
+// restore gp
+ add gp = 0, r39 // A
+ add out0 = 0, in0 // A
+
+// load the integer and float registers
+ ld8 out1 = [r40], 8 // M
+ ldfd f8 = [r41], 8 ;; // M
+
+ ld8 out2 = [r40], 8 // M
+ ldfd f9 = [r41], 8 ;; // M
+
+ ld8 out3 = [r40], 8 // M
+ ldfd f10 = [r41], 8 ;; // M
+
+ ld8 out4 = [r40], 8 // M
+ ldfd f11 = [r41], 8 ;; // M
+
+ ld8 out5 = [r40], 8 // M
+ ldfd f12 = [r41], 8 ;; // M
+// 16 * methodIndex
+ shladd r11 = in1, 4, r0 // A
+
+ ld8 out6 = [r40], 8 // M
+ ldfd f13 = [r41], 8 ;; // M
+
+ ld8 out7 = [r40], 8 // M
+ ldfd f14 = [r41], 8 // M
+ addp4 r8 = 0, in0 ;; // A
+
+// look up virtual base table and dispatch to target subroutine
+// This section assumes 32 bit pointer mode, and virtual base table
+// layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html
+
+// load base table
+ ld4 r8 = [r8] ;; // M
+ addp4 r8 = r11, r8 ;; // A
+
+ // first entry is jump pointer, second entry is gp
+ addp4 r9 = 8, r8 ;; // A
+// load jump pointer
+ ld8 r8 = [r8]
+
+// load gp
+ ld8 gp = [r9] ;; // M
+ mov b6 = r8 ;; // I
+
+// branch to target virtual function
+ br.call.sptk.few rp = b6 ;; // B
+
+// epilog
+ mov ar.pfs = r37 // I
+ mov rp = r36 ;; // I
+
+ add sp = 0, r38 // A
+ add gp = 0, r39 // A
+ br.ret.sptk.few rp ;; // B
+
+ .endp
+
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s
new file mode 100644
index 0000000000..3ee7b7971a
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s
@@ -0,0 +1,146 @@
+
+// Select C numeric constant
+ .radix C
+// for 64 bit mode, use .psr abi64
+ .psr abi64
+// little endian
+ .psr lsb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'NS_InvokeByIndex'
+ .proc NS_InvokeByIndex
+// manual bundling
+ .explicit
+
+// extern "C" uint32_t
+// invoke_copy_to_stack(uint64_t* d,
+// const uint32_t paramCount, nsXPTCVariant* s)
+ .global invoke_copy_to_stack
+// .exclass invoke_copy_to_stack, @fullyvisible
+ .type invoke_copy_to_stack,@function
+
+// .exclass NS_InvokeByIndex, @fullyvisible
+ .type NS_InvokeByIndex,@function
+
+// XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+// uint32_t paramCount, nsXPTCVariant* params);
+NS_InvokeByIndex::
+ .prologue
+ .save ar.pfs, r37
+// allocate 4 input args, 6 local args, and 8 output args
+ alloc r37 = ar.pfs, 4, 6, 8, 0 // M
+ nop.i 0 ;; // I
+
+// unwind table already knows gp, no need to specify anything
+ add r39 = 0, gp // A
+ .save rp, r36
+ mov r36 = rp // I
+ .vframe r38
+ add r38 = 0, sp ;; // A
+
+// We first calculate the amount of extra memory stack space required
+// for the arguments, and register storage.
+// We then call invoke_copy_to_stack() to write the argument contents
+// to the specified memory regions.
+// We then copy the integer arguments to integer registers, and floating
+// arguments to float registers.
+// Lastly we load the virtual table jump pointer, and call the target
+// subroutine.
+
+// in0 : that
+// in1 : methodIndex
+// in2 : paramCount
+// in3 : params
+
+// stack frame size is 16 + (8 * even(paramCount)) + 64 + 64
+// 16 byte frame header
+// 8 * even(paramCount) memory argument area
+// 64 bytes integer register area
+// 64 bytes float register area
+// This scheme makes sure stack fram size is a multiple of 16
+
+ .body
+ add r10 = 8, r0 // A
+// r41 points to float register area
+ add r41 = -64, sp // A
+// r40 points to int register area
+ add r40 = -128, sp ;; // A
+
+ add out1 = 0, r40 // A
+ add out2 = 0, r41 // A
+ tbit.z p14,p15 = in2,0 ;; // I
+
+// compute 8 * even(paramCount)
+(p14) shladd r11 = in2, 3, r0 ;; // A
+(p15) shladd r11 = in2, 3, r10 ;; // A
+ sub out0 = r40, r11 ;; // A
+
+// advance the stack frame
+ add sp = -16, out0 // A
+ add out3 = 0, in2 // A
+ add out4 = 0, in3 // A
+
+// branch to invoke_copy_to_stack
+ br.call.sptk.few rp = invoke_copy_to_stack ;; // B
+
+// restore gp
+ add gp = 0, r39 // A
+ add out0 = 0, in0 // A
+
+// load the integer and float registers
+ ld8 out1 = [r40], 8 // M
+ ldfd f8 = [r41], 8 ;; // M
+
+ ld8 out2 = [r40], 8 // M
+ ldfd f9 = [r41], 8 ;; // M
+
+ ld8 out3 = [r40], 8 // M
+ ldfd f10 = [r41], 8 ;; // M
+
+ ld8 out4 = [r40], 8 // M
+ ldfd f11 = [r41], 8 ;; // M
+
+ ld8 out5 = [r40], 8 // M
+ ldfd f12 = [r41], 8 ;; // M
+// 16 * methodIndex
+ shladd r11 = in1, 4, r0 // A
+
+ ld8 out6 = [r40], 8 // M
+ ldfd f13 = [r41], 8 ;; // M
+
+ ld8 out7 = [r40], 8 // M
+ ldfd f14 = [r41], 8 // M
+ add r8 = 0, in0 ;; // A
+
+// look up virtual base table and dispatch to target subroutine
+// This section assumes 64 bit pointer mode, and virtual base table
+// layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html
+
+// load base table
+ ld8 r8 = [r8] ;; // M
+ add r8 = r11, r8 ;; // A
+
+ // first entry is jump pointer, second entry is gp
+ add r9 = 8, r8 ;; // A
+// load jump pointer
+ ld8 r8 = [r8]
+
+// load gp
+ ld8 gp = [r9] ;; // M
+ mov b6 = r8 ;; // I
+
+// branch to target virtual function
+ br.call.sptk.few rp = b6 ;; // B
+
+// epilog
+ mov ar.pfs = r37 // I
+ mov rp = r36 ;; // I
+
+ add sp = 0, r38 // A
+ add gp = 0, r39 // A
+ br.ret.sptk.few rp ;; // B
+
+ .endp
+
+/* Magic indicating no need for an executable stack */
+ .section .note.GNU-stack, "", @progbits
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_loongarch64.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_loongarch64.S
new file mode 100644
index 0000000000..f0a6662986
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_loongarch64.S
@@ -0,0 +1,92 @@
+/* This Source Code Form subject to the terms of Mozilla Public
+ * License, v. 2.0 If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+ .set NGPREGS, 8
+ .set NFPREGS, 8
+
+ .text
+ .globl _NS_InvokeByIndex
+ .type _NS_InvokeByIndex, @function
+/*
+ * _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ * uint32_t paramCount, nsXPTCVariant* params)
+ */
+_NS_InvokeByIndex:
+ .cfi_startproc
+ addi.d $sp, $sp, -32
+ .cfi_def_cfa_offset 32
+ st.d $s0, $sp, 16
+ .cfi_offset 23, -16
+ st.d $s1, $sp, 8
+ .cfi_offset 24, -24
+ st.d $s2, $sp, 0
+ .cfi_offset 25, -32
+ st.d $ra, $sp, 24
+ .cfi_offset 1, -8
+
+ move $s2, $a0
+ move $s1, $a1
+ move $s0, $sp
+ .cfi_def_cfa_register 23
+
+ /* 16-bytes alignment */
+ addi.d $a0, $a2, 1
+ li.d $t4, 0xfffffffffffffffe
+ and $a0, $a0, $t4
+ slli.d $a0, $a0, 3
+ sub.d $sp, $sp, $a0
+ move $a4, $sp
+
+ addi.d $sp, $sp, -8*(NFPREGS+NGPREGS)
+ move $a0, $sp
+ addi.d $a1, $sp, 8*NGPREGS
+
+ bl invoke_copy_to_stack
+
+ /* 1st argument is this */
+ move $a0, $s2
+
+ ld.d $a1, $sp, 8
+ ld.d $a2, $sp, 16
+ ld.d $a3, $sp, 24
+ ld.d $a4, $sp, 32
+ ld.d $a5, $sp, 40
+ ld.d $a6, $sp, 48
+ ld.d $a7, $sp, 56
+
+ fld.d $fa0, $sp, 64
+ fld.d $fa1, $sp, 72
+ fld.d $fa2, $sp, 80
+ fld.d $fa3, $sp, 88
+ fld.d $fa4, $sp, 96
+ fld.d $fa5, $sp, 104
+ fld.d $fa6, $sp, 112
+ fld.d $fa7, $sp, 120
+
+ addi.d $sp, $sp, 8*(NGPREGS+NFPREGS)
+
+ ld.d $s2, $s2, 0
+ slli.w $s1, $s1, 3
+ add.d $s2, $s2, $s1
+ ld.d $t3, $s2, 0
+ jirl $ra, $t3, 0
+
+ move $sp, $s0
+ .cfi_def_cfa_register 3
+ ld.d $s0, $sp, 16
+ .cfi_restore 23
+ ld.d $s1, $sp, 8
+ .cfi_restore 24
+ ld.d $s2, $sp, 0
+ .cfi_restore 25
+ ld.d $ra, $sp, 24
+ .cfi_restore 1
+ addi.d $sp, $sp, 32
+ .cfi_def_cfa_offset -32
+ jirl $zero, $ra, 0
+ .cfi_endproc
+ .size _NS_InvokeByIndex, .-_NS_InvokeByIndex
+ .section .note.GNU-stack, "", @progbits
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S
new file mode 100644
index 0000000000..32ff3b3565
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S
@@ -0,0 +1,134 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* This code is for MIPS using the O32 ABI. */
+
+#ifdef ANDROID
+#include <asm/regdef.h>
+#include <asm/asm.h>
+#include <machine/asm.h>
+#else
+#include <sys/regdef.h>
+#include <sys/asm.h>
+#endif
+
+# NARGSAVE is the argument space in the callers frame, including extra
+# 'shadowed' space for the argument registers. The minimum of 4
+# argument slots is sometimes predefined in the header files.
+#ifndef NARGSAVE
+#define NARGSAVE 4
+#endif
+
+#define LOCALSZ 3 /* gp, fp, ra */
+#define FRAMESZ ((((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK)
+
+#define RAOFF (FRAMESZ - (1*SZREG))
+#define FPOFF (FRAMESZ - (2*SZREG))
+#define GPOFF (FRAMESZ - (3*SZREG))
+
+#define A0OFF (FRAMESZ + (0*SZREG))
+#define A1OFF (FRAMESZ + (1*SZREG))
+#define A2OFF (FRAMESZ + (2*SZREG))
+#define A3OFF (FRAMESZ + (3*SZREG))
+
+ .text
+
+#
+# _NS_InvokeByIndex(that, methodIndex, paramCount, params)
+# a0 a1 a2 a3
+
+ .globl _NS_InvokeByIndex
+ .align 2
+ .type _NS_InvokeByIndex,@function
+ .ent _NS_InvokeByIndex,0
+ .frame fp, FRAMESZ, ra
+_NS_InvokeByIndex:
+ SETUP_GP
+ subu sp, FRAMESZ
+
+ # specify the save register mask for gp, fp, ra, a3 - a0
+ .mask 0xD00000F0, RAOFF-FRAMESZ
+
+ sw ra, RAOFF(sp)
+ sw fp, FPOFF(sp)
+
+ # we can't use .cprestore in a variable stack frame
+ sw gp, GPOFF(sp)
+
+ sw a0, A0OFF(sp)
+ sw a1, A1OFF(sp)
+ sw a2, A2OFF(sp)
+ sw a3, A3OFF(sp)
+
+ # save bottom of fixed frame
+ move fp, sp
+
+ # extern "C" uint32
+ # invoke_count_words(uint32_t paramCount, nsXPTCVariant* s);
+ la t9, invoke_count_words
+ move a0, a2
+ move a1, a3
+ jalr t9
+ lw gp, GPOFF(fp)
+
+ # allocate variable stack, with a size of:
+ # wordsize (of 4 bytes) * result (already aligned to dword)
+ # but a minimum of 16 byte
+ sll v0, 2
+ slt t0, v0, 16
+ beqz t0, 1f
+ li v0, 16
+1: subu sp, v0
+
+ # let a0 point to the bottom of the variable stack, allocate
+ # another fixed stack for:
+ # extern "C" void
+ # invoke_copy_to_stack(uint32_t* d, uint32_t paramCount,
+ # nsXPTCVariant* s);
+ la t9, invoke_copy_to_stack
+ move a0, sp
+ lw a1, A2OFF(fp)
+ lw a2, A3OFF(fp)
+ subu sp, 16
+ jalr t9
+ lw gp, GPOFF(fp)
+
+ # back to the variable stack frame
+ addu sp, 16
+
+ # calculate the function we need to jump to, which must then be
+ # stored in t9
+ lw a0, A0OFF(fp) # a0 = set "that" to be "this"
+ lw t0, A1OFF(fp) # a1 = methodIndex
+ lw t9, 0(a0)
+ # t0 = methodIndex << PTRLOG
+ sll t0, t0, PTRLOG
+ addu t9, t0
+ lw t9, (t9)
+
+ # Set a1-a3 to what invoke_copy_to_stack told us. a0 is already
+ # the "this" pointer. We don't have to care about floating
+ # point arguments, the non-FP "this" pointer as first argument
+ # means they'll never be used.
+ lw a1, 1*SZREG(sp)
+ lw a2, 2*SZREG(sp)
+ lw a3, 3*SZREG(sp)
+
+ jalr t9
+ # Micro-optimization: There's no gp usage below this point, so
+ # we don't reload.
+ # lw gp, GPOFF(fp)
+
+ # leave variable stack frame
+ move sp, fp
+
+ lw ra, RAOFF(sp)
+ lw fp, FPOFF(sp)
+
+ addiu sp, FRAMESZ
+ j ra
+END(_NS_InvokeByIndex)
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S
new file mode 100644
index 0000000000..d2c5595ab4
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S
@@ -0,0 +1,121 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+.text
+.globl invoke_count_words
+.globl invoke_copy_to_stack
+
+LOCALSZ=7 # a0, a1, a2, a3, s0, ra, gp
+FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+
+RAOFF=FRAMESZ-(1*SZREG)
+A0OFF=FRAMESZ-(2*SZREG)
+A1OFF=FRAMESZ-(3*SZREG)
+A2OFF=FRAMESZ-(4*SZREG)
+A3OFF=FRAMESZ-(5*SZREG)
+S0OFF=FRAMESZ-(6*SZREG)
+GPOFF=FRAMESZ-(7*SZREG)
+
+#
+# _NS_InvokeByIndex(that, methodIndex, paramCount, params)
+# a0 a1 a2 a3
+
+NESTED(_NS_InvokeByIndex, FRAMESZ, ra)
+ PTR_SUBU sp, FRAMESZ
+ SETUP_GP64(GPOFF, _NS_InvokeByIndex)
+
+ REG_S ra, RAOFF(sp)
+ REG_S a0, A0OFF(sp)
+ REG_S a1, A1OFF(sp)
+ REG_S a2, A2OFF(sp)
+ REG_S a3, A3OFF(sp)
+ REG_S s0, S0OFF(sp)
+
+ # invoke_count_words(paramCount, params)
+ move a0, a2
+ move a1, a3
+ jal invoke_count_words
+
+ # invoke_copy_to_stack(uint32_t* d, uint32_t paramCount,
+ # nsXPTCVariant* s, uint32_t *reg)
+
+ REG_L a1, A2OFF(sp) # a1 - paramCount
+ REG_L a2, A3OFF(sp) # a2 - params
+
+ # save sp before we copy the params to the stack
+ move t0, sp
+
+ # assume full size of 16 bytes per param to be safe
+ sll v0, 4 # 16 bytes * num params
+ PTR_SUBU sp, sp, v0 # make room
+ move a0, sp # a0 - param stack address
+
+ # create temporary stack space to write int and fp regs
+ PTR_SUBU sp, 64 # 64 = 8 regs of 8 bytes
+ move a3, sp
+
+ # save the old sp and save the arg stack
+ PTR_SUBU sp, sp, 16
+ REG_S t0, 0(sp)
+ REG_S a0, 8(sp)
+
+ # copy the param into the stack areas
+ jal invoke_copy_to_stack
+
+ REG_L t3, 8(sp) # get previous a0
+ REG_L s0, 0(sp) # get orig sp back and save away our stack pointer
+
+ REG_L a0, A0OFF(s0) # a0 - that
+ REG_L a1, A1OFF(s0) # a1 - methodIndex
+
+ # t1 = methodIndex * pow(2, PTRLOG)
+ # (use shift instead of mult)
+ sll t1, a1, PTRLOG
+
+ # calculate the function we need to jump to,
+ # which must then be saved in t9
+ PTR_L t9, 0(a0)
+ PTR_ADDU t9, t9, t1
+ PTR_L t9, (t9)
+
+ # get register save area from invoke_copy_to_stack
+ PTR_SUBU t1, t3, 64
+
+ # a1..a7 and f13..f19 should now be set to what
+ # invoke_copy_to_stack told us. skip a0 and f12
+ # because that's the "this" pointer
+
+ REG_L a1, 0(t1)
+ REG_L a2, 8(t1)
+ REG_L a3, 16(t1)
+ REG_L a4, 24(t1)
+ REG_L a5, 32(t1)
+ REG_L a6, 40(t1)
+ REG_L a7, 48(t1)
+
+ l.d $f13, 0(t1)
+ l.d $f14, 8(t1)
+ l.d $f15, 16(t1)
+ l.d $f16, 24(t1)
+ l.d $f17, 32(t1)
+ l.d $f18, 40(t1)
+ l.d $f19, 48(t1)
+
+ # create the stack pointer for the function
+ move sp, t3
+
+ jalr t9
+
+ ## restore stack pointer.
+ move sp, s0
+
+ RESTORE_GP64
+ REG_L ra, RAOFF(sp)
+ REG_L s0, S0OFF(sp)
+ PTR_ADDU sp, FRAMESZ
+ j ra
+.end _NS_InvokeByIndex
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s
new file mode 100644
index 0000000000..6fa9a86ba8
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s
@@ -0,0 +1,131 @@
+ .LEVEL 1.1
+framesz .EQU 128
+
+; XPTC_InvokeByIndex(nsISuppots* that, uint32_t methodIndex,
+; uint32_t paramCount, nsXPTCVariant* params);
+
+; g++ need to compile everything with -fvtable-thunks !
+
+ .SPACE $TEXT$,SORT=8
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
+XPTC_InvokeByIndex
+ .PROC
+ .CALLINFO CALLER,FRAME=72,ENTRY_GR=%r3,SAVE_RP,SAVE_SP,ARGS_SAVED,ALLOCA_FRAME
+
+ ; frame marker takes 48 bytes,
+ ; register spill area takes 8 bytes,
+ ; local stack area takes 72 bytes result in 128 bytes total
+
+ .ENTRY
+ STW %rp,-20(%sp)
+ STW,MA %r3,128(%sp)
+
+ LDO -framesz(%r30),%r28
+ STW %r28,-4(%r30) ; save previous sp
+ STW %r19,-32(%r30)
+
+ STW %r26,-36-framesz(%r30) ; save argument registers in
+ STW %r25,-40-framesz(%r30) ; in PREVIOUS frame
+ STW %r24,-44-framesz(%r30) ;
+ STW %r23,-48-framesz(%r30) ;
+
+ B,L .+8,%r2
+ ADDIL L'invoke_count_bytes-$PIC_pcrel$1+4,%r2,%r1
+ LDO R'invoke_count_bytes-$PIC_pcrel$2+8(%r1),%r1
+$PIC_pcrel$1
+ LDSID (%r1),%r31
+$PIC_pcrel$2
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26;out=28
+ BE,L 0(%sr0,%r1),%r31
+ COPY %r31,%r2
+
+ CMPIB,>= 0,%r28, .+76
+ COPY %r30,%r3 ; copy stack ptr to saved stack ptr
+ ADD %r30,%r28,%r30 ; extend stack frame
+ LDW -4(%r3),%r28 ; move frame
+ STW %r28,-4(%r30)
+ LDW -8(%r3),%r28
+ STW %r28,-8(%r30)
+ LDW -12(%r3),%r28
+ STW %r28,-12(%r30)
+ LDW -16(%r3),%r28
+ STW %r28,-16(%r30)
+ LDW -20(%r3),%r28
+ STW %r28,-20(%r30)
+ LDW -24(%r3),%r28
+ STW %r28,-24(%r30)
+ LDW -28(%r3),%r28
+ STW %r28,-28(%r30)
+ LDW -32(%r3),%r28
+ STW %r28,-32(%r30)
+
+ LDO -40(%r30),%r26 ; load copy address
+ LDW -44-framesz(%r3),%r25 ; load rest of 2 arguments
+ LDW -48-framesz(%r3),%r24 ;
+
+ LDW -32(%r30),%r19 ; shared lib call destroys r19; reload
+ B,L .+8,%r2
+ ADDIL L'invoke_copy_to_stack-$PIC_pcrel$3+4,%r2,%r1
+ LDO R'invoke_copy_to_stack-$PIC_pcrel$4+8(%r1),%r1
+$PIC_pcrel$3
+ LDSID (%r1),%r31
+$PIC_pcrel$4
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26
+ BE,L 0(%sr0,%r1),%r31
+ COPY %r31,%r2
+
+ LDO -48(%r30),%r20
+ EXTRW,U,= %r28,31,1,%r22
+ FLDD 0(%r20),%fr7 ; load double arg 1
+ EXTRW,U,= %r28,30,1,%r22
+ FLDW 8(%r20),%fr5L ; load float arg 1
+ EXTRW,U,= %r28,29,1,%r22
+ FLDW 4(%r20),%fr6L ; load float arg 2
+ EXTRW,U,= %r28,28,1,%r22
+ FLDW 0(%r20),%fr7L ; load float arg 3
+
+ LDW -36-framesz(%r3),%r26 ; load ptr to 'that'
+ LDW -40(%r30),%r25 ; load the rest of dispatch argument registers
+ LDW -44(%r30),%r24
+ LDW -48(%r30),%r23
+
+ LDW -36-framesz(%r3),%r20 ; load vtable addr
+ LDW -40-framesz(%r3),%r28 ; load index
+ LDW 0(%r20),%r20 ; follow vtable
+ LDO 16(%r20),%r20 ; offset vtable by 16 bytes (g++: 8, aCC: 16)
+ SH2ADDL %r28,%r20,%r28 ; add 4*index to vtable entry
+ LDW 0(%r28),%r22 ; load vtable entry
+
+ B,L .+8,%r2
+ ADDIL L'$$dyncall_external-$PIC_pcrel$5+4,%r2,%r1
+ LDO R'$$dyncall_external-$PIC_pcrel$6+8(%r1),%r1
+$PIC_pcrel$5
+ LDSID (%r1),%r31
+$PIC_pcrel$6
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+;in=22-26;out=28;
+ BE,L 0(%sr0,%r1),%r31
+ COPY %r31,%r2
+
+ LDW -32(%r30),%r19
+ COPY %r3,%r30 ; restore saved stack ptr
+
+ LDW -148(%sp),%rp
+ BVE (%rp)
+ .EXIT
+ LDW,MB -128(%sp),%r3
+
+ .PROCEND ;in=23,24,25,26;
+
+ .ALIGN 8
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+ .IMPORT $$dyncall_external,MILLICODE
+ .IMPORT invoke_count_bytes,CODE
+ .IMPORT invoke_copy_to_stack,CODE
+ .EXPORT XPTC_InvokeByIndex,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR,LONG_RETURN
+ .END
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s
new file mode 100644
index 0000000000..7a207addfd
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s
@@ -0,0 +1,108 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ .LEVEL 1.1
+ .text
+ .align 4
+
+framesz:
+ .equ 128
+
+.globl NS_InvokeByIndex
+ .type NS_InvokeByIndex, @function
+
+
+NS_InvokeByIndex:
+ .PROC
+ .CALLINFO FRAME=72, CALLER,SAVE_RP, SAVE_SP, ENTRY_GR=3
+ .ENTRY
+
+; frame marker takes 48 bytes,
+; register spill area takes 8 bytes,
+; local stack area takes 72 bytes result in 128 bytes total
+
+ STW %rp,-20(%sp)
+ STW,MA %r3,128(%sp)
+
+ LDO -framesz(%r30),%r28
+ STW %r28,-4(%r30) ; save previous sp
+ STW %r19,-32(%r30)
+
+ STW %r26,-36-framesz(%r30) ; save argument registers in
+ STW %r25,-40-framesz(%r30) ; in PREVIOUS frame
+ STW %r24,-44-framesz(%r30) ;
+ STW %r23,-48-framesz(%r30) ;
+
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26;out=28
+ BL invoke_count_bytes,%r31
+ COPY %r31,%r2
+
+ CMPIB,>= 0,%r28, .+76
+ COPY %r30,%r3 ; copy stack ptr to saved stack ptr
+ ADD %r30,%r28,%r30 ; extend stack frame
+ LDW -4(%r3),%r28 ; move frame
+ STW %r28,-4(%r30)
+ LDW -8(%r3),%r28
+ STW %r28,-8(%r30)
+ LDW -12(%r3),%r28
+ STW %r28,-12(%r30)
+ LDW -16(%r3),%r28
+ STW %r28,-16(%r30)
+ LDW -20(%r3),%r28
+ STW %r28,-20(%r30)
+ LDW -24(%r3),%r28
+ STW %r28,-24(%r30)
+ LDW -28(%r3),%r28
+ STW %r28,-28(%r30)
+ LDW -32(%r3),%r28
+ STW %r28,-32(%r30)
+
+ LDO -40(%r30),%r26 ; load copy address
+ LDW -44-framesz(%r3),%r25 ; load rest of 2 arguments
+ LDW -48-framesz(%r3),%r24 ;
+
+ LDW -32(%r30),%r19 ; shared lib call destroys r19; reload
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26
+ BL invoke_copy_to_stack,%r31
+ COPY %r31,%r2
+
+ LDO -48(%r30),%r20
+ EXTRW,U,= %r28,31,1,%r22
+ FLDD 0(%r20),%fr7 ; load double arg 1
+ EXTRW,U,= %r28,30,1,%r22
+ FLDW 8(%r20),%fr5L ; load float arg 1
+ EXTRW,U,= %r28,29,1,%r22
+ FLDW 4(%r20),%fr6L ; load float arg 2
+ EXTRW,U,= %r28,28,1,%r22
+ FLDW 0(%r20),%fr7L ; load float arg 3
+
+ LDW -36-framesz(%r3),%r26 ; load ptr to 'that'
+ LDW -40(%r30),%r25 ; load the rest of dispatch argument registers
+ LDW -44(%r30),%r24
+ LDW -48(%r30),%r23
+
+ LDW -36-framesz(%r3),%r20 ; load vtable addr
+ LDW -40-framesz(%r3),%r28 ; load index
+ LDW 0(%r20),%r20 ; follow vtable
+ SH2ADDL %r28,%r20,%r28 ; add 4*index to vtable entry
+ LDW 0(%r28),%r22 ; load vtable entry
+
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR ;in=22-26;out=28;
+ BL $$dyncall,%r31
+ COPY %r31,%r2
+
+ LDW -32(%r30),%r19
+ COPY %r3,%r30 ; restore saved stack ptr
+
+ LDW -148(%sp),%rp
+ LDWM -128(%sp),%r3
+ BV,N (%rp)
+ NOP
+ .EXIT
+ .PROCEND ;in=23,24,25,26;
+ .SIZE NS_InvokeByIndex, .-NS_InvokeByIndex
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S
new file mode 100644
index 0000000000..d2cab6c813
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S
@@ -0,0 +1,167 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+.set r0,0; .set r1,1; .set r2,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+# The ABI defines a fixed stack frame area of 4 doublewords (ELFv2)
+# or 6 doublewords (ELFv1); the last of these doublewords is used
+# as TOC pointer save area. The fixed area is followed by a parameter
+# save area of 8 doublewords (used for vararg routines), followed
+# by space for parameters passed on the stack.
+#
+# We set STACK_TOC to the offset of the TOC pointer save area, and
+# STACK_PARAMS to the offset of the first on-stack parameter.
+
+#if _CALL_ELF == 2
+#define STACK_TOC 24
+#define STACK_PARAMS 96
+#else
+#define STACK_TOC 40
+#define STACK_PARAMS 112
+#endif
+
+#
+# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+#if _CALL_ELF == 2
+ .section ".text"
+ .type NS_InvokeByIndex,@function
+ .globl NS_InvokeByIndex
+ .align 2
+NS_InvokeByIndex:
+0: addis 2,12,(.TOC.-0b)@ha
+ addi 2,2,(.TOC.-0b)@l
+ .localentry NS_InvokeByIndex,.-NS_InvokeByIndex
+#else
+ .section ".toc","aw"
+ .section ".text"
+ .align 2
+ .globl NS_InvokeByIndex
+ .section ".opd","aw"
+ .align 3
+NS_InvokeByIndex:
+ .quad .NS_InvokeByIndex,.TOC.@tocbase
+ .previous
+ .type NS_InvokeByIndex,@function
+.NS_InvokeByIndex:
+#endif
+ mflr 0
+ std 0,16(r1)
+
+ std r29,-24(r1)
+ std r30,-16(r1)
+ std r31,-8(r1)
+
+ mr r29,r3 # Save 'that' in r29
+ mr r30,r4 # Save 'methodIndex' in r30
+ mr r31,r1 # Save old frame
+
+ # Allocate stack frame with space for params. Since at least the
+ # first 7 parameters (not including 'that') will be in registers,
+ # we don't actually need stack space for those. We must ensure
+ # that the stack remains 16-byte aligned.
+ #
+ # | (fixed area + | | 7 GP | 13 FP | 3 NV |
+ # | param. save) |(params)........| regs | regs | regs |
+ # (r1)......(+STACK_PARAMS)... (-23*8).(-16*8).(-3*8)..(r31)
+
+ # +stack frame, -unused stack params, +regs storage, +1 for alignment
+ addi r7,r5,((STACK_PARAMS/8)-7+7+13+3+1)
+ rldicr r7,r7,3,59 # multiply by 8 and mask with ~15
+ neg r7,r7
+ stdux r1,r1,r7
+
+
+ # Call invoke_copy_to_stack(uint64_t* gpregs, double* fpregs,
+ # uint32_t paramCount, nsXPTCVariant* s,
+ # uint64_t* d))
+
+ # r5, r6 are passed through intact (paramCount, params)
+ # r7 (d) has to be r1+STACK_PARAMS
+ # -- where parameters are passed on the stack.
+ # r3, r4 are above that, easier to address from r31 than from r1
+
+ subi r3,r31,(23*8) # r3 --> GPRS
+ subi r4,r31,(16*8) # r4 --> FPRS
+ addi r7,r1,STACK_PARAMS # r7 --> params
+ bl invoke_copy_to_stack
+ nop
+
+ # Set up to invoke function
+
+ ld r9,0(r29) # vtable (r29 is 'that')
+ mr r3,r29 # self is first arg, obviously
+
+ sldi r30,r30,3 # Find function descriptor
+ add r9,r9,r30
+ ld r12,0(r9)
+
+ std r2,STACK_TOC(r1) # Save r2 (TOC pointer)
+
+#if _CALL_ELF == 2
+ mtctr r12
+#else
+ ld r0,0(r12) # Actual address from fd.
+ mtctr 0
+ ld r11,16(r12) # Environment pointer from fd.
+ ld r2,8(r12) # TOC pointer from fd.
+#endif
+
+ # Load FP and GP registers as required
+ ld r4, -(23*8)(r31)
+ ld r5, -(22*8)(r31)
+ ld r6, -(21*8)(r31)
+ ld r7, -(20*8)(r31)
+ ld r8, -(19*8)(r31)
+ ld r9, -(18*8)(r31)
+ ld r10, -(17*8)(r31)
+
+ lfd f1, -(16*8)(r31)
+ lfd f2, -(15*8)(r31)
+ lfd f3, -(14*8)(r31)
+ lfd f4, -(13*8)(r31)
+ lfd f5, -(12*8)(r31)
+ lfd f6, -(11*8)(r31)
+ lfd f7, -(10*8)(r31)
+ lfd f8, -(9*8)(r31)
+ lfd f9, -(8*8)(r31)
+ lfd f10, -(7*8)(r31)
+ lfd f11, -(6*8)(r31)
+ lfd f12, -(5*8)(r31)
+ lfd f13, -(4*8)(r31)
+
+ bctrl # Do it
+
+ ld r2,STACK_TOC(r1) # Load our own TOC pointer
+ ld r1,0(r1) # Revert stack frame
+ ld 0,16(r1) # Reload lr
+ mtlr 0
+ ld 29,-24(r1) # Restore NVGPRS
+ ld 30,-16(r1)
+ ld 31,-8(r1)
+ blr
+
+#if _CALL_ELF == 2
+ .size NS_InvokeByIndex,.-NS_InvokeByIndex
+#else
+ .size NS_InvokeByIndex,.-.NS_InvokeByIndex
+#endif
+
+ # Magic indicating no need for an executable stack
+ .section .note.GNU-stack, "", @progbits
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s
new file mode 100644
index 0000000000..eb6b6661d3
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s
@@ -0,0 +1,129 @@
+#
+# -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+.set BO_IF,12
+.set CR0_EQ,2
+
+
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .NS_InvokeByIndex
+ .globl NS_InvokeByIndex{DS}
+ .extern .invoke_copy_to_stack
+ .extern ._ptrgl{PR}
+
+
+#
+# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+.NS_InvokeByIndex:
+ mflr r0
+ stw r31,-4(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ stw r3,24(sp) # that
+ stw r4,28(sp) # methodIndex
+ stw r5,32(sp) # paramCount
+ stw r6,36(sp) # params
+ stw r0,8(sp)
+ stwu sp,-136(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,168(sp) # paramCount
+ lwz r5,172(sp) # params
+ mr r6,sp # fprData
+ slwi r3,r4,3 # number of bytes of stack required
+ # at most 8*paramCount
+ addi r3,r3,28 # linkage area
+ mr r31,sp # save original stack top
+ subfc sp,r3,sp # bump the stack
+ addi r3,sp,28 # parameter pointer excludes linkage area size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31) # Restore floating point registers
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,160(r31) # that
+ lwz r4,0(r3) # get vTable from 'that'
+ lwz r5,164(r31) # methodIndex
+ slwi r5,r5,3 # methodIndex * 8
+ addi r5,r5,8 # step over junk at start of vTable !
+ lwzx r11,r5,r4 # get function pointer
+
+ addi r5,r5,4 # We need to manually adjust the 'that' pointer, this is CFRONT based
+ lwzx r5,r4,r5 # offset = r4(vtable) + r5(methodIndex offset) - 4
+ add r3,r5,r3 # adjust 'that' r3 = r3 + r5
+
+ lwz r4,28(sp)
+ lwz r5,32(sp)
+ lwz r6,36(sp)
+ lwz r7,40(sp)
+ lwz r8,44(sp)
+ lwz r9,48(sp)
+ lwz r10,52(sp)
+
+ bl ._ptrgl{PR}
+ nop
+
+ mr sp,r31
+ lwz r0,144(sp)
+ addi sp,sp,136
+ mtlr r0
+ lwz r31,-4(sp)
+ blr
+
+
+# .data section
+
+ .toc # 0x00000038
+T.18.NS_InvokeByIndex:
+ .tc H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS}
+
+ .csect NS_InvokeByIndex{DS}
+ .long .NS_InvokeByIndex # "\0\0\0\0"
+ .long TOC{TC0} # "\0\0\0008"
+ .long 0x00000000 # "\0\0\0\0"
+# End csect NS_InvokeByIndex{DS}
+
+# .bss section
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s
new file mode 100644
index 0000000000..722583de5b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s
@@ -0,0 +1,128 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+.set BO_IF,12
+.set CR0_EQ,2
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .NS_InvokeByIndex
+ .globl NS_InvokeByIndex{DS}
+ .extern .invoke_copy_to_stack
+ .extern ._ptrgl{PR}
+
+#
+# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+.NS_InvokeByIndex:
+ mflr r0
+ std r31,-8(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ std r3,48(sp) # that
+ std r4,56(sp) # methodIndex
+ std r5,64(sp) # paramCount
+ std r6,72(sp) # params
+ std r0,16(sp)
+ stdu sp,-168(sp) # 2*24=48 for linkage area,
+ # 8*13=104 for fprData area
+ # 16 for saved registers
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ ld r4,232(sp) # paramCount (168+8+56)
+ ld r5,240(sp) # params
+ mr r6,sp # fprData
+ sldi r3,r4,3 # number of bytes of stack required
+ # is at most numParams*8
+ addi r3,r3,56 # linkage area (48) + this (8)
+ mr r31,sp # save original stack top
+ subfc sp,r3,sp # bump the stack
+ addi r3,sp,56 # parameter pointer excludes linkage area
+ # size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31) # Restore floating point registers
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ ld r3,216(r31) # that (168+48)
+ ld r4,0(r3) # get vTable from 'that'
+ ld r5,224(r31) # methodIndex (168+56)
+ sldi r5,r5,3 # methodIndex * 8
+ # No junk at the start of 64bit vtable !!!
+ ldx r11,r5,r4 # get function pointer (this jumps
+ # either to the function if no adjustment
+ # is needed (displacement = 0), or it
+ # jumps to the thunk code, which will jump
+ # to the function at the end)
+
+ # No adjustment of the that pointer in 64bit mode, this is done
+ # by the thunk code
+
+ ld r4,56(sp)
+ ld r5,64(sp)
+ ld r6,72(sp)
+ ld r7,80(sp)
+ ld r8,88(sp)
+ ld r9,96(sp)
+ ld r10,104(sp)
+
+ bl ._ptrgl{PR}
+ nop
+
+ mr sp,r31
+ ld r0,184(sp) # 168+16
+ addi sp,sp,168
+ mtlr r0
+ ld r31,-8(sp)
+ blr
+
+# .data section
+
+ .toc # 0x00000038
+T.18.NS_InvokeByIndex:
+ .tc H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS}
+
+ .csect NS_InvokeByIndex{DS}
+ .llong .NS_InvokeByIndex # "\0\0\0\0"
+ .llong TOC{TC0} # "\0\0\0008"
+ .llong 0x00000000 # "\0\0\0\0"
+# End csect NS_InvokeByIndex{DS}
+
+# .bss section
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s
new file mode 100644
index 0000000000..414a6536fa
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s
@@ -0,0 +1,124 @@
+#
+# -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+.set BO_IF,12
+.set CR0_EQ,2
+
+
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .NS_InvokeByIndex
+ .globl NS_InvokeByIndex{DS}
+ .extern .invoke_copy_to_stack
+ .extern ._ptrgl{PR}
+
+
+#
+# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+.NS_InvokeByIndex:
+ mflr r0
+ stw r31,-4(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ stw r3,24(sp) # that
+ stw r4,28(sp) # methodIndex
+ stw r5,32(sp) # paramCount
+ stw r6,36(sp) # params
+ stw r0,8(sp)
+ stwu sp,-136(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,168(sp) # paramCount
+ lwz r5,172(sp) # params
+ mr r6,sp # fprData
+ slwi r3,r4,3 # number of bytes of stack required
+ # at most 8*paramCount
+ addi r3,r3,28 # linkage area
+ mr r31,sp # save original stack top
+ subfc sp,r3,sp # bump the stack
+ addi r3,sp,28 # parameter pointer excludes linkage area size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31) # Restore floating point registers
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,160(r31) # that
+ lwz r4,0(r3) # get vTable from 'that'
+ lwz r5,164(r31) # methodIndex
+ slwi r5,r5,2 # methodIndex * 4
+ lwzx r11,r5,r4 # get function pointer
+
+ lwz r4,28(sp)
+ lwz r5,32(sp)
+ lwz r6,36(sp)
+ lwz r7,40(sp)
+ lwz r8,44(sp)
+ lwz r9,48(sp)
+ lwz r10,52(sp)
+
+ bl ._ptrgl{PR}
+ nop
+
+ mr sp,r31
+ lwz r0,144(sp)
+ addi sp,sp,136
+ mtlr r0
+ lwz r31,-4(sp)
+ blr
+
+
+# .data section
+
+ .toc # 0x00000038
+T.18.NS_InvokeByIndex:
+ .tc H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS}
+
+ .csect NS_InvokeByIndex{DS}
+ .long .NS_InvokeByIndex # "\0\0\0\0"
+ .long TOC{TC0} # "\0\0\0008"
+ .long 0x00000000 # "\0\0\0\0"
+# End csect NS_InvokeByIndex{DS}
+
+# .bss section
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S
new file mode 100644
index 0000000000..619e428a9c
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S
@@ -0,0 +1,98 @@
+// -*- Mode: Asm -*-
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl NS_InvokeByIndex
+ .type NS_InvokeByIndex,@function
+
+//
+// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+// uint32_t paramCount, nsXPTCVariant* params)
+//
+
+NS_InvokeByIndex:
+ stwu sp,-32(sp) // setup standard stack frame
+ mflr r0 // save LR
+ stw r3,8(sp) // r3 <= that
+ stw r4,12(sp) // r4 <= methodIndex
+ stw r30,16(sp)
+ stw r31,20(sp)
+
+ stw r0,36(sp) // store LR backchain
+ mr r31,sp
+
+ rlwinm r10,r5,3,0,27 // r10 = (ParamCount * 2 * 4) & ~0x0f
+ addi r0,r10,96 // reserve stack for GPR and FPR register save area r0 = r10 + 96
+ lwz r9,0(sp) // r9 = backchain
+ neg r0,r0
+ stwux r9,sp,r0 // reserve stack space and save SP backchain
+
+ addi r3,sp,8 // r3 <= args
+ mr r4,r5 // r4 <= paramCount
+ mr r5,r6 // r5 <= params
+ add r6,r3,r10 // r6 <= gpregs ( == args + r10 )
+ mr r30,r6 // store in r30 for use later...
+#ifndef __NO_FPRS__
+ addi r7,r6,32 // r7 <= fpregs ( == gpregs + 32 )
+#else
+ li r7, 0
+#endif
+
+ bl invoke_copy_to_stack@local // (args, paramCount, params, gpregs, fpregs)
+#ifndef __NO_FPRS__
+ lfd f1,32(r30) // load FP registers with method parameters
+ lfd f2,40(r30)
+ lfd f3,48(r30)
+ lfd f4,56(r30)
+ lfd f5,64(r30)
+ lfd f6,72(r30)
+ lfd f7,80(r30)
+ lfd f8,88(r30)
+#endif
+ lwz r3,8(r31) // r3 <= that
+ lwz r4,12(r31) // r4 <= methodIndex
+ lwz r5,0(r3) // r5 <= vtable ( == *that )
+ slwi r4,r4,2 // convert to offset ( *= 4 )
+ lwzx r0,r5,r4 // r0 <= methodpointer ( == vtable + offset )
+
+ lwz r4,4(r30) // load GP regs with method parameters
+ lwz r5,8(r30)
+ lwz r6,12(r30)
+ lwz r7,16(r30)
+ lwz r8,20(r30)
+ lwz r9,24(r30)
+ lwz r10,28(r30)
+
+ mtlr r0 // copy methodpointer to LR
+ blrl // call method
+
+ lwz r30,16(r31) // restore r30 & r31
+ lwz r31,20(r31)
+
+ lwz r11,0(sp) // clean up the stack
+ lwz r0,4(r11)
+ mtlr r0
+ mr sp,r11
+ blr
+
+ /* Magic indicating no need for an executable stack */
+ .section .note.GNU-stack, "", @progbits
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S
new file mode 100644
index 0000000000..2f8dc73b2e
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S
@@ -0,0 +1,94 @@
+// -*- Mode: Asm -*-
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl NS_InvokeByIndex
+ .type NS_InvokeByIndex,@function
+
+//
+// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+// uint32_t paramCount, nsXPTCVariant* params)
+//
+
+NS_InvokeByIndex:
+ stwu sp,-32(sp) // setup standard stack frame
+ mflr r0 // save LR
+ stw r3,8(sp) // r3 <= that
+ stw r4,12(sp) // r4 <= methodIndex
+ stw r30,16(sp)
+ stw r31,20(sp)
+
+ stw r0,36(sp) // store LR backchain
+ mr r31,sp
+
+ rlwinm r10,r5,3,0,27 // r10 = (ParamCount * 2 * 4) & ~0x0f
+ addi r0,r10,96 // reserve stack for GPR and FPR register save area r0 = r10 + 96
+ lwz r9,0(sp) // r9 = backchain
+ neg r0,r0
+ stwux r9,sp,r0 // reserve stack space and save SP backchain
+
+ addi r3,sp,8 // r3 <= args
+ mr r4,r5 // r4 <= paramCount
+ mr r5,r6 // r5 <= params
+ add r6,r3,r10 // r6 <= gpregs ( == args + r10 )
+ mr r30,r6 // store in r30 for use later...
+ addi r7,r6,32 // r7 <= fpregs ( == gpregs + 32 )
+
+ bl invoke_copy_to_stack@local // (args, paramCount, params, gpregs, fpregs)
+
+ lfd f1,32(r30) // load FP registers with method parameters
+ lfd f2,40(r30)
+ lfd f3,48(r30)
+ lfd f4,56(r30)
+ lfd f5,64(r30)
+ lfd f6,72(r30)
+ lfd f7,80(r30)
+ lfd f8,88(r30)
+
+ lwz r3,8(r31) // r3 <= that
+ lwz r4,12(r31) // r4 <= methodIndex
+ lwz r5,0(r3) // r5 <= vtable ( == *that )
+ slwi r4,r4,2 // convert to offset ( *= 4 )
+ lwzx r0,r5,r4 // r0 <= methodpointer ( == vtable + offset )
+
+ lwz r4,4(r30) // load GP regs with method parameters
+ lwz r5,8(r30)
+ lwz r6,12(r30)
+ lwz r7,16(r30)
+ lwz r8,20(r30)
+ lwz r9,24(r30)
+ lwz r10,28(r30)
+
+ mtlr r0 // copy methodpointer to LR
+ blrl // call method
+
+ lwz r30,16(r31) // restore r30 & r31
+ lwz r31,20(r31)
+
+ lwz r11,0(sp) // clean up the stack
+ lwz r0,4(r11)
+ mtlr r0
+ mr sp,r11
+ blr
+
+ // Magic indicating no need for an executable stack
+ .section .note.GNU-stack, "", @progbits
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s
new file mode 100644
index 0000000000..1dc12b2b30
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s
@@ -0,0 +1,142 @@
+#
+# -*- Mode: Asm -*-
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#
+# ** Assumed vtable layout (obtained by disassembling with gdb):
+# ** 4 bytes per vtable entry, skip 0th and 1st entries, so the mapping
+# ** from index to entry is (4 * index) + 8.
+#
+
+.text
+ .align 2
+#
+# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+.globl __NS_InvokeByIndex
+__NS_InvokeByIndex:
+ mflr r0
+ stw r31,-4(r1)
+#
+# save off the incoming values in the callers parameter area
+#
+ stw r3,24(r1) ; that
+ stw r4,28(r1) ; methodIndex
+ stw r5,32(r1) ; paramCount
+ stw r6,36(r1) ; params
+ stw r0,8(r1)
+ stwu r1,-144(r1) ; 24 for linkage area,
+ ; 8*13 for fprData area,
+ ; 8 for saved registers,
+ ; 8 to keep stack 16-byte aligned
+
+# set up for and call 'invoke_count_words' to get new stack size
+#
+ mr r3,r5
+ mr r4,r6
+
+ stwu r1,-24(r1)
+ bl L_invoke_count_words$stub
+ lwz r1,0(r1)
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,176(r1) ; paramCount
+ lwz r5,180(r1) ; params
+ mr r6,r1 ; fprData
+ slwi r3,r3,2 ; number of stack bytes required
+ addi r3,r3,28 ; linkage area
+ mr r31,r1 ; save original stack top
+ sub r1,r1,r3 ; bump the stack
+ clrrwi r1,r1,4 ; keep the stack 16-byte aligned
+ addi r3,r31,144 ; act like real alloca, so 0(sp) always
+ stw r3,0(r1) ; points back to previous stack frame
+ addi r3,r1,28 ; parameter pointer excludes linkage area size + 'this'
+
+# create "temporary" stack frame for _invoke_copy_to_stack to operate in.
+ stwu r1,-40(r1)
+ bl L_invoke_copy_to_stack$stub
+# remove temporary stack frame.
+ lwz r1,0(r1)
+
+ lfd f1,0(r31)
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,168(r31) ; that
+ lwz r4,0(r3) ; get vTable from 'that'
+ lwz r5,172(r31) ; methodIndex
+ slwi r5,r5,2 ; methodIndex * 4
+ lwzx r12,r5,r4 ; get function pointer
+
+ lwz r4,28(r1)
+ lwz r5,32(r1)
+ lwz r6,36(r1)
+ lwz r7,40(r1)
+ lwz r8,44(r1)
+ lwz r9,48(r1)
+ lwz r10,52(r1)
+
+ mtlr r12
+ blrl
+
+ mr r1,r31
+ lwz r0,152(r1)
+ addi r1,r1,144
+ mtlr r0
+ lwz r31,-4(r1)
+
+ blr
+
+.picsymbol_stub
+L_invoke_count_words$stub:
+ .indirect_symbol _invoke_count_words
+ mflr r0
+ bcl 20,31,L1$pb
+L1$pb:
+ mflr r11
+ addis r11,r11,ha16(L1$lz-L1$pb)
+ mtlr r0
+ lwz r12,lo16(L1$lz-L1$pb)(r11)
+ mtctr r12
+ addi r11,r11,lo16(L1$lz-L1$pb)
+ bctr
+.lazy_symbol_pointer
+L1$lz:
+ .indirect_symbol _invoke_count_words
+ .long dyld_stub_binding_helper
+
+
+.picsymbol_stub
+L_invoke_copy_to_stack$stub:
+ .indirect_symbol _invoke_copy_to_stack
+ mflr r0
+ bcl 20,31,L2$pb
+L2$pb:
+ mflr r11
+ addis r11,r11,ha16(L2$lz-L2$pb)
+ mtlr r0
+ lwz r12,lo16(L2$lz-L2$pb)(r11)
+ mtctr r12
+ addi r11,r11,lo16(L2$lz-L2$pb)
+ bctr
+.lazy_symbol_pointer
+L2$lz:
+ .indirect_symbol _invoke_copy_to_stack
+ .long dyld_stub_binding_helper
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_riscv64.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_riscv64.S
new file mode 100644
index 0000000000..4606523296
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_riscv64.S
@@ -0,0 +1,89 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ .set NGPREGS, 8
+ .set NFPREGS, 8
+
+ .text
+ .globl _NS_InvokeByIndex
+ .type _NS_InvokeByIndex, @function
+/*
+ * _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ * uint32_t paramCount, nsXPTCVariant* params)
+ */
+_NS_InvokeByIndex:
+ .cfi_startproc
+ addi sp, sp, -32
+ .cfi_adjust_cfa_offset 32
+ sd s0, 16(sp)
+ .cfi_rel_offset s0, 16
+ sd s1, 8(sp)
+ .cfi_rel_offset s1, 8
+ sd s2, 0(sp)
+ .cfi_rel_offset s2, 0
+ sd ra, 24(sp)
+ .cfi_rel_offset ra, 24
+
+ mv s2, a0
+ mv s1, a1
+ mv s0, sp
+ .cfi_def_cfa_register s0
+
+ /* 16-bytes alignment */
+ addiw a0, a2, 1
+ andi a0, a0, -2
+ slli a0, a0, 3
+ sub sp, sp, a0
+ mv a4, sp
+
+ addi sp, sp, -8*(NGPREGS+NFPREGS)
+ mv a0, sp
+ addi a1, sp, 8*NGPREGS
+
+ call invoke_copy_to_stack
+
+ /* 1st argument is this */
+ mv a0, s2
+
+ ld a1, 8(sp)
+ ld a2, 16(sp)
+ ld a3, 24(sp)
+ ld a4, 32(sp)
+ ld a5, 40(sp)
+ ld a6, 48(sp)
+ ld a7, 56(sp)
+
+ fld fa0, 64(sp)
+ fld fa1, 72(sp)
+ fld fa2, 80(sp)
+ fld fa3, 88(sp)
+ fld fa4, 96(sp)
+ fld fa5, 104(sp)
+ fld fa6, 112(sp)
+ fld fa7, 120(sp)
+
+ addi sp, sp, 8*(NGPREGS+NFPREGS)
+
+ ld s2, 0(s2)
+ slliw s1, s1, 3
+ add s2, s2, s1
+ ld t0, 0(s2)
+ jalr t0
+
+ mv sp, s0
+ .cfi_def_cfa_register sp
+ ld s0, 16(sp)
+ .cfi_restore s0
+ ld s1, 8(sp)
+ .cfi_restore s1
+ ld s2, 0(sp)
+ .cfi_restore s2
+ ld ra, 24(sp)
+ .cfi_restore ra
+ addi sp, sp, 32
+ .cfi_adjust_cfa_offset -32
+ ret
+ .cfi_endproc
+ .size _NS_InvokeByIndex, . - _NS_InvokeByIndex
+ .section .note.GNU-stack, "", @progbits
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s
new file mode 100644
index 0000000000..dfd6189f83
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s
@@ -0,0 +1,86 @@
+/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ Platform specific code to invoke XPCOM methods on native objects
+ for sparcv9 Solaris.
+
+ See the SPARC Compliance Definition (SCD) Chapter 3
+ for more information about what is going on here, including
+ the use of BIAS (0x7ff).
+ The SCD is available from http://www.sparc.com/.
+*/
+
+ .global NS_InvokeByIndex
+ .type NS_InvokeByIndex, #function
+
+/*
+ NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+*/
+NS_InvokeByIndex:
+ save %sp,-(128 + 64),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 64
+ sll %i2,4,%l0 ! assume the worst case
+ ! paramCount * 2 * 8 bytes
+ cmp %l0, 0 ! are there any args? If not,
+ be .invoke ! no need to copy args to stack
+ nop
+
+ sub %sp,%l0,%sp ! create the additional stack space
+ add %sp,0x7ff+136,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+
+!
+! load arguments from stack into the outgoing registers
+! BIAS is 0x7ff (2047)
+!
+
+! load the %o1..5 64bit (extended word) output registers registers
+ ldx [%sp + 0x7ff + 136],%o1 ! %i1
+ ldx [%sp + 0x7ff + 144],%o2 ! %i2
+ ldx [%sp + 0x7ff + 152],%o3 ! %i3
+ ldx [%sp + 0x7ff + 160],%o4 ! %i4
+ ldx [%sp + 0x7ff + 168],%o5 ! %i5
+
+! load the even number double registers starting with %f2
+ ldd [%sp + 0x7ff + 136],%f2
+ ldd [%sp + 0x7ff + 144],%f4
+ ldd [%sp + 0x7ff + 152],%f6
+ ldd [%sp + 0x7ff + 160],%f8
+ ldd [%sp + 0x7ff + 168],%f10
+ ldd [%sp + 0x7ff + 176],%f12
+ ldd [%sp + 0x7ff + 184],%f14
+ ldd [%sp + 0x7ff + 192],%f16
+ ldd [%sp + 0x7ff + 200],%f18
+ ldd [%sp + 0x7ff + 208],%f20
+ ldd [%sp + 0x7ff + 216],%f22
+ ldd [%sp + 0x7ff + 224],%f24
+ ldd [%sp + 0x7ff + 232],%f26
+ ldd [%sp + 0x7ff + 240],%f28
+ ldd [%sp + 0x7ff + 248],%f30
+
+!
+! calculate the target address from the vtable
+!
+.invoke:
+ sll %i1,3,%l0 ! index *= 8
+! add %l0,16,%l0 ! there are 2 extra entries in the vTable (16bytes)
+ ldx [%i0],%l1 ! *that --> address of vtable
+ ldx [%l0 + %l1],%l0 ! that->vtable[index * 8 + 16] --> address
+
+ jmpl %l0,%o7 ! call the routine
+ mov %i0,%o0 ! move 'this' pointer to out register
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
+
+ .size NS_InvokeByIndex, .-NS_InvokeByIndex
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s
new file mode 100644
index 0000000000..36196805e8
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Platform specific code to invoke XPCOM methods on native objects for
+ * Linux/Sparc with gcc 3 ABI.
+ */
+ .global NS_InvokeByIndex
+/*
+ * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ * uint32_t paramCount, nsXPTCVariant* params);
+ *
+ */
+NS_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,2,%i1 ! multiply index by 4
+ add %i1,%l1,%l1 ! l1 now points to vTable entry
+ ld [%l1],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s
new file mode 100644
index 0000000000..893432a5e8
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?)
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,3,%i1
+ add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry
+ lduh [%l1],%l0 ! this adjustor
+ sll %l0,16,%l0 ! sign extend to 32 bits
+ sra %l0,16,%l0
+ add %l0,%i0,%i0 ! adjust this
+ ld [%l1 + 4],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s
new file mode 100644
index 0000000000..1ef6953703
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?)
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,3,%i1
+ add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry
+ lduh [%l1],%l0 ! this adjustor
+ sll %l0,16,%l0 ! sign extend to 32 bits
+ sra %l0,16,%l0
+ add %l0,%i0,%i0 ! adjust this
+ ld [%l1 + 4],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_64_unix.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_64_unix.S
new file mode 100644
index 0000000000..0cb7ff37c7
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_64_unix.S
@@ -0,0 +1,117 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Darwin gives a leading '_' to symbols defined in C code.
+#ifdef XP_DARWIN
+#define SYM(x) _ ## x
+#else
+#define SYM(x) x
+#endif
+
+#define CFI_STARTPROC .cfi_startproc
+#define CFI_ENDPROC .cfi_endproc
+#define CFI_DEF_CFA_OFFSET(offset) .cfi_def_cfa_offset offset
+#define CFI_OFFSET(reg, offset) .cfi_offset reg, offset
+#define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
+#define CFI_DEF_CFA(reg, offset) .cfi_def_cfa reg, offset
+
+.intel_syntax noprefix
+
+# nsresult NS_InvokeByIndex(nsISupports* this, uint32_t aVtableIndex,
+# uint32_t argc, nsXPTCVariant* argv);
+.text
+.global SYM(NS_InvokeByIndex)
+#ifndef XP_DARWIN
+.type NS_InvokeByIndex, @function
+#endif
+.align 4
+SYM(NS_InvokeByIndex):
+ CFI_STARTPROC
+ push rbp
+ CFI_DEF_CFA_OFFSET(16)
+ CFI_OFFSET(6, -16)
+ mov rbp, rsp
+ CFI_DEF_CFA_REGISTER(6)
+
+# save r12 and r13 because we use them and they are callee saved.
+ push r12
+ push r13
+ CFI_OFFSET(12, -24)
+ CFI_OFFSET(13, -32)
+
+# save this and the vtable index because we need them after setting up the
+# stack.
+ mov r12, rdi
+ mov r13, rsi
+
+# allocate space for stack arguments, in theory we only need 8 * (argc - 5)
+# bytes because at least 5 arguments will go in registers, but for now it is
+# just simpler to allocate 8 * argc bytes. Note that we treat the this
+# pointer specially.
+ lea eax, [edx * 8]
+ sub rsp, rax
+
+# If there is an odd number of args the stack can be misaligned so realign it.
+ and rsp, 0xfffffffffffffff0
+
+# pass the stack slot area to InvokeCopyToStack.
+ mov r8, rsp
+
+# setup space for the register slots: there are 5 integer ones and 8 floating
+# point ones. So we need 104 bytes of space, but we allocate 112 to keep rsp
+# aligned to 16 bytes.
+ sub rsp, 112
+
+# the first argument to InvokeCopyToStack is the integer register area, and the
+# second is the floating point area.
+ mov rdi, rsp
+ lea rsi, [rsp + 40]
+
+# The 3rd and 4th arguments to InvokeCopyToStack are already in the right
+# registers. So now we can just call InvokeCopyToStack.
+ call SYM(InvokeCopyToStack)
+
+# setup this
+ mov rdi, r12
+
+# copy the integer arguments into place.
+ mov rsi, [rsp]
+ mov rdx, [rsp + 8]
+ mov rcx, [rsp + 16]
+ mov r8, [rsp + 24]
+ mov r9, [rsp + 32]
+
+# copy the float arguments into place
+ movsd xmm0, [rsp + 40]
+ movsd xmm1, [rsp + 48]
+ movsd xmm2, [rsp + 56]
+ movsd xmm3, [rsp + 64]
+ movsd xmm4, [rsp + 72]
+ movsd xmm5, [rsp + 80]
+ movsd xmm6, [rsp + 88]
+ movsd xmm7, [rsp + 96]
+
+# get rid of the scratch space for registers
+ add rsp, 112
+
+# load the function pointer and call
+ lea eax, [r13d * 8]
+ add rax, [rdi]
+ call [rax]
+
+# r12 and r13 were pushed relative to the old stack pointer which is now the
+# frame pointer.
+ mov r12, [rbp - 0x8]
+ mov r13, [rbp - 0x10]
+
+ mov rsp, rbp
+ pop rbp
+ CFI_DEF_CFA(7, 8)
+ ret
+ CFI_ENDPROC
+
+#ifndef XP_DARWIN
+// Magic indicating no need for an executable stack
+.section .note.GNU-stack, "", @progbits
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp
new file mode 100644
index 0000000000..e6b7932e8d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp
@@ -0,0 +1,18 @@
+/* -*- Mode: C -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if defined(__i386__)
+#include "xptcinvoke_gcc_x86_unix.cpp"
+#elif defined(__x86_64__)
+#include "xptcinvoke_x86_64_unix.cpp"
+#elif defined(__ppc__)
+#include "xptcinvoke_ppc_rhapsody.cpp"
+#elif defined(__arm__)
+#include "xptcinvoke_arm.cpp"
+#elif defined(__aarch64__)
+#include "xptcinvoke_aarch64.cpp"
+#else
+#error unknown cpu architecture
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp
new file mode 100644
index 0000000000..2e834a7e3c
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp
@@ -0,0 +1,97 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+#include "xptc_gcc_x86_unix.h"
+
+extern "C" {
+static void ATTRIBUTE_USED __attribute__ ((regparm(3)))
+invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d)
+{
+ for(uint32_t i = paramCount; i >0; i--, d++, s++)
+ {
+ if(s->IsIndirect())
+ {
+ *((void**)d) = &s->val;
+ continue;
+ }
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ default : *((void**)d) = s->val.p; break;
+ }
+ }
+}
+} // extern "C"
+
+/*
+ EXPORT_XPCOM_API(nsresult)
+ NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+ Each param takes at most two 4-byte words.
+ It doesn't matter if we push too many words, and calculating the exact
+ amount takes time.
+
+ that = ebp + 0x08
+ methodIndex = ebp + 0x0c
+ paramCount = ebp + 0x10
+ params = ebp + 0x14
+
+*/
+
+__asm__ (
+ ".text\n\t"
+/* alignment here seems unimportant here; this was 16, now it's 2 which
+ is what xptcstubs uses. */
+ ".align 2\n\t"
+ ".globl " SYMBOL_UNDERSCORE "NS_InvokeByIndex\n\t"
+#ifndef XP_MACOSX
+ ".type " SYMBOL_UNDERSCORE "NS_InvokeByIndex,@function\n"
+#endif
+ SYMBOL_UNDERSCORE "NS_InvokeByIndex:\n\t"
+ "pushl %ebp\n\t"
+ "movl %esp, %ebp\n\t"
+ "movl 0x10(%ebp), %eax\n\t"
+ "leal 0(,%eax,8),%edx\n\t"
+
+ /* set up call frame for method. */
+ "subl %edx, %esp\n\t" /* make room for params. */
+/* Align to maximum x86 data size: 128 bits == 16 bytes == XMM register size.
+ * This is to avoid protection faults where SSE+ alignment of stack pointer
+ * is assumed and required, e.g. by GCC4's -ftree-vectorize option.
+ */
+ "andl $0xfffffff0, %esp\n\t" /* drop(?) stack ptr to 128-bit align */
+/* $esp should be aligned to a 16-byte boundary here (note we include an
+ * additional 4 bytes in a later push instruction). This will ensure $ebp
+ * in the function called below is aligned to a 0x8 boundary. SSE instructions
+ * like movapd/movdqa expect memory operand to be aligned on a 16-byte
+ * boundary. The GCC compiler will generate the memory operand using $ebp
+ * with an 8-byte offset.
+ */
+ "subl $0xc, %esp\n\t" /* lower again; push/call below will re-align */
+ "movl %esp, %ecx\n\t" /* ecx = d */
+ "movl 8(%ebp), %edx\n\t" /* edx = this */
+ "pushl %edx\n\t" /* push this. esp % 16 == 0 */
+
+ "movl 0x14(%ebp), %edx\n\t"
+ "call " SYMBOL_UNDERSCORE "invoke_copy_to_stack\n\t"
+ "movl 0x08(%ebp), %ecx\n\t" /* 'that' */
+ "movl (%ecx), %edx\n\t"
+ "movl 0x0c(%ebp), %eax\n\t" /* function index */
+ "leal (%edx,%eax,4), %edx\n\t"
+ "call *(%edx)\n\t"
+ "movl %ebp, %esp\n\t"
+ "popl %ebp\n\t"
+ "ret\n"
+#ifndef XP_MACOSX
+ ".size " SYMBOL_UNDERSCORE "NS_InvokeByIndex, . -" SYMBOL_UNDERSCORE "NS_InvokeByIndex\n\t"
+#endif
+);
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp
new file mode 100644
index 0000000000..969029f13e
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp
@@ -0,0 +1,129 @@
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xptcprivate.h"
+
+// "This code is for IA64 only"
+
+
+/* invoke_copy_to_stack() will copy from variant array 's' to
+ * the stack argument area 'mloc', the integer register area 'iloc', and
+ * the float register area 'floc'.
+ *
+ */
+extern "C" void
+invoke_copy_to_stack(uint64_t* mloc, uint64_t* iloc, uint64_t* floc,
+ const uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint64_t* dest = mloc;
+ uint32_t len = paramCount;
+ nsXPTCVariant* source = s;
+
+ uint32_t indx;
+ uint32_t endlen;
+ endlen = (len > 7) ? 7 : len;
+ /* handle the memory arguments */
+ for (indx = 7; indx < len; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].ptr;
+#endif
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_DOUBLE: *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+#else
+ {
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].val.p;
+ }
+#endif
+ }
+ ++dest;
+ }
+ /* process register arguments */
+ dest = iloc;
+ for (indx = 0; indx < endlen; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].ptr;
+#endif
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT :
+ *((double*) (floc++)) = (double) source[indx].val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ *((double*) (floc++)) = source[indx].val.d;
+ break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+#else
+ {
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].val.p;
+ }
+#endif
+ }
+ ++dest;
+ }
+
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp
new file mode 100644
index 0000000000..acd9de081b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp
@@ -0,0 +1,99 @@
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xptcprivate.h"
+
+#include <stdint.h>
+
+// "This code is for IA64 only"
+
+
+/* invoke_copy_to_stack() will copy from variant array 's' to
+ * the stack argument area 'mloc', the integer register area 'iloc', and
+ * the float register area 'floc'.
+ *
+ */
+extern "C" void
+invoke_copy_to_stack(uint64_t* mloc, uint64_t* iloc, uint64_t* floc,
+ const uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint64_t* dest = mloc;
+ uint32_t len = paramCount;
+ nsXPTCVariant* source = s;
+
+ uint32_t indx;
+ uint32_t endlen;
+ endlen = (len > 7) ? 7 : len;
+ /* handle the memory arguments */
+ for (indx = 7; indx < len; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_DOUBLE: *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+ }
+ ++dest;
+ }
+ /* process register arguments */
+ dest = iloc;
+ for (indx = 0; indx < endlen; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT :
+ *((double*) (floc++)) = (double) source[indx].val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ *((double*) (floc++)) = source[indx].val.d;
+ break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+ }
+ ++dest;
+ }
+
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp
new file mode 100644
index 0000000000..dc111e4358
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp
@@ -0,0 +1,144 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+/* Prototype specifies unmangled function name and disables unused warning */
+static void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+__asm__("invoke_copy_to_stack") __attribute__((used));
+
+static void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *d = (uint64_t)s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *d = (uint64_t)s->val.i8; break;
+ case nsXPTType::T_I16 : *d = (uint64_t)s->val.i16; break;
+ case nsXPTType::T_I32 : *d = (uint64_t)s->val.i32; break;
+ case nsXPTType::T_I64 : *d = (uint64_t)s->val.i64; break;
+ case nsXPTType::T_U8 : *d = (uint64_t)s->val.u8; break;
+ case nsXPTType::T_U16 : *d = (uint64_t)s->val.u16; break;
+ case nsXPTType::T_U32 : *d = (uint64_t)s->val.u32; break;
+ case nsXPTType::T_U64 : *d = (uint64_t)s->val.u64; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // convert floats to doubles if they are to be passed
+ // via registers so we can just deal with doubles later
+ union { uint64_t u64; double d; } t;
+ t.d = (double)s->val.f;
+ *d = t.u64;
+ }
+ else
+ // otherwise copy to stack normally
+ *d = (uint64_t)s->val.u32;
+ break;
+ case nsXPTType::T_DOUBLE : *d = (uint64_t)s->val.u64; break;
+ case nsXPTType::T_BOOL : *d = (uint64_t)s->val.b; break;
+ case nsXPTType::T_CHAR : *d = (uint64_t)s->val.c; break;
+ case nsXPTType::T_WCHAR : *d = (uint64_t)s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *d = (uint64_t)s->val.p;
+ break;
+ }
+ }
+}
+
+/*
+ * EXPORT_XPCOM_API(nsresult)
+ * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ * uint32_t paramCount, nsXPTCVariant* params)
+ */
+__asm__(
+ "#### NS_InvokeByIndex ####\n"
+".text\n\t"
+ ".align 5\n\t"
+ ".globl NS_InvokeByIndex\n\t"
+ ".ent NS_InvokeByIndex\n"
+"NS_InvokeByIndex:\n\t"
+ ".frame $15,32,$26,0\n\t"
+ ".mask 0x4008000,-32\n\t"
+ "ldgp $29,0($27)\n"
+"$NS_InvokeByIndex..ng:\n\t"
+ "subq $30,32,$30\n\t"
+ "stq $26,0($30)\n\t"
+ "stq $15,8($30)\n\t"
+ "bis $30,$30,$15\n\t"
+ ".prologue 1\n\t"
+
+ /*
+ * Allocate enough stack space to hold the greater of 6 or "paramCount"+1
+ * parameters. (+1 for "this" pointer) Room for at least 6 parameters
+ * is required for storage of those passed via registers.
+ */
+
+ "bis $31,5,$2\n\t" /* count = MAX(5, "paramCount") */
+ "cmplt $2,$18,$1\n\t"
+ "cmovne $1,$18,$2\n\t"
+ "s8addq $2,16,$1\n\t" /* room for count+1 params (8 bytes each) */
+ "bic $1,15,$1\n\t" /* stack space is rounded up to 0 % 16 */
+ "subq $30,$1,$30\n\t"
+
+ "stq $16,0($30)\n\t" /* save "that" (as "this" pointer) */
+ "stq $17,16($15)\n\t" /* save "methodIndex" */
+
+ "addq $30,8,$16\n\t" /* pass stack pointer */
+ "bis $18,$18,$17\n\t" /* pass "paramCount" */
+ "bis $19,$19,$18\n\t" /* pass "params" */
+ "bsr $26,$invoke_copy_to_stack..ng\n\t" /* call invoke_copy_to_stack */
+
+ /*
+ * Copy the first 6 parameters to registers and remove from stack frame.
+ * Both the integer and floating point registers are set for each parameter
+ * except the first which is the "this" pointer. (integer only)
+ * The floating point registers are all set as doubles since the
+ * invoke_copy_to_stack function should have converted the floats.
+ */
+ "ldq $16,0($30)\n\t" /* integer registers */
+ "ldq $17,8($30)\n\t"
+ "ldq $18,16($30)\n\t"
+ "ldq $19,24($30)\n\t"
+ "ldq $20,32($30)\n\t"
+ "ldq $21,40($30)\n\t"
+ "ldt $f17,8($30)\n\t" /* floating point registers */
+ "ldt $f18,16($30)\n\t"
+ "ldt $f19,24($30)\n\t"
+ "ldt $f20,32($30)\n\t"
+ "ldt $f21,40($30)\n\t"
+
+ "addq $30,48,$30\n\t" /* remove params from stack */
+
+ /*
+ * Call the virtual function with the constructed stack frame.
+ */
+ "bis $16,$16,$1\n\t" /* load "this" */
+ "ldq $2,16($15)\n\t" /* load "methodIndex" */
+ "ldq $1,0($1)\n\t" /* load vtable */
+ "s8addq $2,$31,$2\n\t" /* vtable index = "methodIndex" * 8 */
+ "addq $1,$2,$1\n\t"
+ "ldq $27,0($1)\n\t" /* load address of function */
+ "jsr $26,($27),0\n\t" /* call virtual function */
+ "ldgp $29,0($26)\n\t"
+
+ "bis $15,$15,$30\n\t"
+ "ldq $26,0($30)\n\t"
+ "ldq $15,8($30)\n\t"
+ "addq $30,32,$30\n\t"
+ "ret $31,($26),1\n\t"
+ ".end NS_InvokeByIndex"
+ );
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp
new file mode 100644
index 0000000000..c5fa2f94bd
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp
@@ -0,0 +1,194 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+
+static uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t overflow = 0, gpr = 1 /*this*/, fpr = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5) gpr++; else overflow++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 4) gpr+=2; else gpr=5, overflow+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 4) gpr+=2; else gpr=5, overflow+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 2) fpr++; else overflow++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 2) fpr++; else overflow+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ }
+ }
+ /* Round up number of overflow words to ensure stack
+ stays aligned to 8 bytes. */
+ return (overflow + 1) & ~1;
+}
+
+static void
+invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d_ov, uint32_t overflow)
+{
+ uint32_t *d_gpr = d_ov + overflow;
+ uint64_t *d_fpr = (uint64_t *)(d_gpr + 4);
+ uint32_t gpr = 1 /*this*/, fpr = 0;
+
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5)
+ *((void**)d_gpr) = s->ptr, d_gpr++, gpr++;
+ else
+ *((void**)d_ov ) = s->ptr, d_ov++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ *((int32_t*) d_gpr) = s->val.i8, d_gpr++, gpr++;
+ else
+ *((int32_t*) d_ov ) = s->val.i8, d_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ *((int32_t*) d_gpr) = s->val.i16, d_gpr++, gpr++;
+ else
+ *((int32_t*) d_ov ) = s->val.i16, d_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ *((int32_t*) d_gpr) = s->val.i32, d_gpr++, gpr++;
+ else
+ *((int32_t*) d_ov ) = s->val.i32, d_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 4)
+ *((int64_t*) d_gpr) = s->val.i64, d_gpr+=2, gpr+=2;
+ else
+ *((int64_t*) d_ov ) = s->val.i64, d_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ *((uint32_t*) d_gpr) = s->val.u8, d_gpr++, gpr++;
+ else
+ *((uint32_t*) d_ov ) = s->val.u8, d_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ *((uint32_t*)d_gpr) = s->val.u16, d_gpr++, gpr++;
+ else
+ *((uint32_t*)d_ov ) = s->val.u16, d_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ *((uint32_t*)d_gpr) = s->val.u32, d_gpr++, gpr++;
+ else
+ *((uint32_t*)d_ov ) = s->val.u32, d_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 4)
+ *((uint64_t*)d_gpr) = s->val.u64, d_gpr+=2, gpr+=2;
+ else
+ *((uint64_t*)d_ov ) = s->val.u64, d_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 2)
+ *((float*) d_fpr) = s->val.f, d_fpr++, fpr++;
+ else
+ *((float*) d_ov ) = s->val.f, d_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 2)
+ *((double*) d_fpr) = s->val.d, d_fpr++, fpr++;
+ else
+ *((double*) d_ov ) = s->val.d, d_ov+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ *((uint32_t*)d_gpr) = s->val.b, d_gpr++, gpr++;
+ else
+ *((uint32_t*)d_ov ) = s->val.b, d_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ *((uint32_t*)d_gpr) = s->val.c, d_gpr++, gpr++;
+ else
+ *((uint32_t*)d_ov ) = s->val.c, d_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ *((uint32_t*)d_gpr) = s->val.wc, d_gpr++, gpr++;
+ else
+ *((uint32_t*)d_ov ) = s->val.wc, d_ov++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5)
+ *((void**) d_gpr) = s->val.p, d_gpr++, gpr++;
+ else
+ *((void**) d_ov ) = s->val.p, d_ov++;
+ break;
+ }
+ }
+}
+
+typedef nsresult (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t, uint32_t, double, double);
+
+// Avoid AddressSanitizer instrumentation for the next function because it
+// depends on __builtin_alloca behavior and alignment that cannot be relied on
+// once the function is compiled with a version of ASan that has dynamic-alloca
+// instrumentation enabled.
+
+MOZ_ASAN_IGNORE
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ vtable_func *vtable = *reinterpret_cast<vtable_func **>(that);
+ vtable_func method = vtable[methodIndex];
+ uint32_t overflow = invoke_count_words (paramCount, params);
+ uint32_t *stack_space = reinterpret_cast<uint32_t *>(__builtin_alloca((overflow + 8 /* 4 32-bits gpr + 2 64-bits fpr */) * 4));
+
+ invoke_copy_to_stack(paramCount, params, stack_space, overflow);
+
+ uint32_t *d_gpr = stack_space + overflow;
+ double *d_fpr = reinterpret_cast<double *>(d_gpr + 4);
+
+ return method(that, d_gpr[0], d_gpr[1], d_gpr[2], d_gpr[3], d_fpr[0], d_fpr[1]);
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp
new file mode 100644
index 0000000000..1be12d4ad3
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp
@@ -0,0 +1,189 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+
+static uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t overflow = 0, gpr = 1 /*this*/, fpr = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsIndirect())
+ {
+ if (gpr < 5) gpr++; else overflow++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ case nsXPTType::T_I64 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ case nsXPTType::T_U64 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_FLOAT :
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 4) fpr++; else overflow++;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ }
+ }
+ /* Round up number of overflow words to ensure stack
+ stays aligned to 8 bytes. */
+ return (overflow + 1) & ~1;
+}
+
+static void
+invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint64_t* d_ov, uint32_t overflow)
+{
+ uint64_t *d_gpr = d_ov + overflow;
+ uint64_t *d_fpr = (uint64_t *)(d_gpr + 4);
+ uint32_t gpr = 1 /*this*/, fpr = 0;
+
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsIndirect())
+ {
+ if (gpr < 5)
+ *((void**)d_gpr) = (void *) &s->val, d_gpr++, gpr++;
+ else
+ *((void**)d_ov ) = (void *) &s->val, d_ov++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ *((int64_t*) d_gpr) = s->val.i8, d_gpr++, gpr++;
+ else
+ *((int64_t*) d_ov ) = s->val.i8, d_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ *((int64_t*) d_gpr) = s->val.i16, d_gpr++, gpr++;
+ else
+ *((int64_t*) d_ov ) = s->val.i16, d_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ *((int64_t*) d_gpr) = s->val.i32, d_gpr++, gpr++;
+ else
+ *((int64_t*) d_ov ) = s->val.i32, d_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 5)
+ *((int64_t*) d_gpr) = s->val.i64, d_gpr++, gpr++;
+ else
+ *((int64_t*) d_ov ) = s->val.i64, d_ov++;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ *((uint64_t*) d_gpr) = s->val.u8, d_gpr++, gpr++;
+ else
+ *((uint64_t*) d_ov ) = s->val.u8, d_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ *((uint64_t*)d_gpr) = s->val.u16, d_gpr++, gpr++;
+ else
+ *((uint64_t*)d_ov ) = s->val.u16, d_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ *((uint64_t*)d_gpr) = s->val.u32, d_gpr++, gpr++;
+ else
+ *((uint64_t*)d_ov ) = s->val.u32, d_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 5)
+ *((uint64_t*)d_gpr) = s->val.u64, d_gpr++, gpr++;
+ else
+ *((uint64_t*)d_ov ) = s->val.u64, d_ov++;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 4)
+ *((float*) d_fpr) = s->val.f, d_fpr++, fpr++;
+ else
+ *(((float*) d_ov )+1) = s->val.f, d_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 4)
+ *((double*) d_fpr) = s->val.d, d_fpr++, fpr++;
+ else
+ *((double*) d_ov ) = s->val.d, d_ov++;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ *((uint64_t*)d_gpr) = s->val.b, d_gpr++, gpr++;
+ else
+ *((uint64_t*)d_ov ) = s->val.b, d_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ *((uint64_t*)d_gpr) = s->val.c, d_gpr++, gpr++;
+ else
+ *((uint64_t*)d_ov ) = s->val.c, d_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ *((uint64_t*)d_gpr) = s->val.wc, d_gpr++, gpr++;
+ else
+ *((uint64_t*)d_ov ) = s->val.wc, d_ov++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5)
+ *((void**) d_gpr) = s->val.p, d_gpr++, gpr++;
+ else
+ *((void**) d_ov ) = s->val.p, d_ov++;
+ break;
+ }
+ }
+}
+
+typedef nsresult (*vtable_func)(nsISupports *, uint64_t, uint64_t, uint64_t, uint64_t, double, double, double, double);
+
+// Avoid AddressSanitizer instrumentation for the next function because it
+// depends on __builtin_alloca behavior and alignment that cannot be relied on
+// once the function is compiled with a version of ASan that has dynamic-alloca
+// instrumentation enabled.
+
+MOZ_ASAN_IGNORE
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ vtable_func *vtable = *reinterpret_cast<vtable_func **>(that);
+ vtable_func method = vtable[methodIndex];
+ uint64_t overflow = invoke_count_words (paramCount, params);
+ uint64_t *stack_space = reinterpret_cast<uint64_t *>(__builtin_alloca((overflow + 8 /* 4 64-bits gpr + 4 64-bits fpr */) * 8));
+ uint64_t result;
+
+ invoke_copy_to_stack(paramCount, params, stack_space, overflow);
+
+ uint64_t *d_gpr = stack_space + overflow;
+ double *d_fpr = reinterpret_cast<double *>(d_gpr + 4);
+
+ return method(that, d_gpr[0], d_gpr[1], d_gpr[2], d_gpr[3], d_fpr[0], d_fpr[1], d_fpr[2], d_fpr[3]);
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp
new file mode 100644
index 0000000000..61bb7b2efd
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp
@@ -0,0 +1,100 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+#include "xptcprivate.h"
+
+extern "C" void invoke_copy_to_stack(uint64_t* gpregs, double* fpregs,
+ uint32_t paramCount, nsXPTCVariant* s,
+ uint64_t* d) {
+ static const uint32_t GPR_COUNT = 8;
+ static const uint32_t FPR_COUNT = 8;
+
+ uint32_t nr_gpr = 1; // skip one GPR register for "this"
+ uint32_t nr_fpr = 0;
+ uint64_t value = 0;
+
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (s->IsIndirect()) {
+ value = (uint64_t)&s->val;
+ } else {
+ switch (s->type) {
+ case nsXPTType::T_FLOAT:
+ break;
+ case nsXPTType::T_DOUBLE:
+ break;
+ case nsXPTType::T_I8:
+ value = s->val.i8;
+ break;
+ case nsXPTType::T_I16:
+ value = s->val.i16;
+ break;
+ case nsXPTType::T_I32:
+ value = s->val.i32;
+ break;
+ case nsXPTType::T_I64:
+ value = s->val.i64;
+ break;
+ case nsXPTType::T_U8:
+ value = s->val.u8;
+ break;
+ case nsXPTType::T_U16:
+ value = s->val.u16;
+ break;
+ case nsXPTType::T_U32:
+ value = s->val.u32;
+ break;
+ case nsXPTType::T_U64:
+ value = s->val.u64;
+ break;
+ case nsXPTType::T_BOOL:
+ value = s->val.b;
+ break;
+ case nsXPTType::T_CHAR:
+ value = s->val.c;
+ break;
+ case nsXPTType::T_WCHAR:
+ value = s->val.wc;
+ break;
+ default:
+ value = (uint64_t)s->val.p;
+ break;
+ }
+ }
+
+ if (!s->IsIndirect() && s->type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT) {
+ fpregs[nr_fpr++] = s->val.d;
+ } else if (nr_gpr < GPR_COUNT) {
+ memcpy(&gpregs[nr_gpr++], &(s->val.d), sizeof(s->val.d));
+ } else {
+ memcpy(d++, &(s->val.d), sizeof(s->val.d));
+ }
+ } else if (!s->IsIndirect() && s->type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT) {
+ memcpy(&fpregs[nr_fpr++], &(s->val.f), sizeof(s->val.f));
+ } else if (nr_gpr < GPR_COUNT) {
+ memcpy(&gpregs[nr_gpr++], &(s->val.f), sizeof(s->val.f));
+ } else {
+ memcpy(d++, &(s->val.f), sizeof(s->val.f));
+ }
+ } else {
+ if (nr_gpr < GPR_COUNT) {
+ gpregs[nr_gpr++] = value;
+ } else {
+ *d++ = value;
+ }
+ }
+ }
+}
+
+extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount,
+ nsXPTCVariant* params);
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, uint32_t paramCount,
+ nsXPTCVariant* params) {
+ return _NS_InvokeByIndex(that, methodIndex, paramCount, params);
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp
new file mode 100644
index 0000000000..b811730c5b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp
@@ -0,0 +1,99 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* This code is for MIPS using the O32 ABI. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#include <stdint.h>
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ // Count a word for a0 even though it's never stored or loaded
+ // We do this only for alignment of register pairs.
+ uint32_t result = 1;
+ for (uint32_t i = 0; i < paramCount; i++, result++, s++)
+ {
+ if (s->IsIndirect())
+ continue;
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE :
+ if (result & 1)
+ result++;
+ result++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return (result + 1) & ~(uint32_t)1;
+}
+
+extern "C" void
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount,
+ nsXPTCVariant* s)
+{
+ // Skip the unused a0 slot, which we keep only for register pair alignment.
+ d++;
+
+ for (uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if (s->IsIndirect())
+ {
+ *((void**)d) = (void*) &s->val;
+ continue;
+ }
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *d = (uint32_t) s->val.i8; break;
+ case nsXPTType::T_I16 : *d = (uint32_t) s->val.i16; break;
+ case nsXPTType::T_I32 : *d = (uint32_t) s->val.i32; break;
+ case nsXPTType::T_I64 :
+ if ((intptr_t)d & 4) d++;
+ *((int64_t*) d) = s->val.i64; d++;
+ break;
+ case nsXPTType::T_U8 : *d = (uint32_t) s->val.u8; break;
+ case nsXPTType::T_U16 : *d = (uint32_t) s->val.u16; break;
+ case nsXPTType::T_U32 : *d = (uint32_t) s->val.u32; break;
+ case nsXPTType::T_U64 :
+ if ((intptr_t)d & 4) d++;
+ *((uint64_t*) d) = s->val.u64; d++;
+ break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE :
+ if ((intptr_t)d & 4) d++;
+ *((double*) d) = s->val.d; d++;
+ break;
+ case nsXPTType::T_BOOL : *d = (bool) s->val.b; break;
+ case nsXPTType::T_CHAR : *d = (char) s->val.c; break;
+ case nsXPTType::T_WCHAR : *d = (wchar_t) s->val.wc; break;
+ default:
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount,
+ nsXPTCVariant* params);
+
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ return _NS_InvokeByIndex(that, methodIndex, paramCount, params);
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp
new file mode 100644
index 0000000000..d10320a997
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp
@@ -0,0 +1,144 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if (_MIPS_SIM != _ABIN32) && (_MIPS_SIM != _ABI64)
+#error "This code is for MIPS n32/n64 only"
+#endif
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ return paramCount;
+}
+
+extern "C" void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount,
+ nsXPTCVariant* s, uint64_t *regs)
+{
+#define N_ARG_REGS 7 /* 8 regs minus 1 for "this" ptr */
+
+ for (uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if (s->IsIndirect()) {
+ if (i < N_ARG_REGS)
+ regs[i] = (uint64_t) &s->val;
+ else
+ *d++ = (uint64_t) &s->val;
+ continue;
+ }
+ switch (s->type) {
+ //
+ // signed types first
+ //
+ case nsXPTType::T_I8:
+ if (i < N_ARG_REGS)
+ ((int64_t*)regs)[i] = s->val.i8;
+ else
+ *d++ = s->val.i8;
+ break;
+ case nsXPTType::T_I16:
+ if (i < N_ARG_REGS)
+ ((int64_t*)regs)[i] = s->val.i16;
+ else
+ *d++ = s->val.i16;
+ break;
+ case nsXPTType::T_I32:
+ if (i < N_ARG_REGS)
+ ((int64_t*)regs)[i] = s->val.i32;
+ else
+ *d++ = s->val.i32;
+ break;
+ case nsXPTType::T_I64:
+ if (i < N_ARG_REGS)
+ ((int64_t*)regs)[i] = s->val.i64;
+ else
+ *d++ = s->val.i64;
+ break;
+ //
+ // unsigned types next
+ //
+ case nsXPTType::T_U8:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u8;
+ else
+ *d++ = s->val.u8;
+ break;
+ case nsXPTType::T_U16:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u16;
+ else
+ *d++ = s->val.u16;
+ break;
+ case nsXPTType::T_U32:
+ if (i < N_ARG_REGS)
+ // 32-bit values need to be sign-extended
+ // in register, so use the signed value.
+ regs[i] = s->val.i32;
+ else
+ *d++ = s->val.u32;
+ break;
+ case nsXPTType::T_U64:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u64;
+ else
+ *d++ = s->val.u64;
+ break;
+ case nsXPTType::T_FLOAT:
+ // the float data formate must not be converted!
+ // Just only copy without conversion.
+ if (i < N_ARG_REGS)
+ *(float*)&regs[i] = s->val.f;
+ else
+ *(float*)d++ = s->val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ if (i < N_ARG_REGS)
+ *(double*)&regs[i] = s->val.d;
+ else
+ *(double*)d++ = s->val.d;
+ break;
+ case nsXPTType::T_BOOL:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.b;
+ else
+ *d++ = s->val.b;
+ break;
+ case nsXPTType::T_CHAR:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.c;
+ else
+ *d++ = s->val.c;
+ break;
+ case nsXPTType::T_WCHAR:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.wc;
+ else
+ *d++ = s->val.wc;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (i < N_ARG_REGS)
+ regs[i] = (uint64_t)s->val.p;
+ else
+ *d++ = (uint64_t)s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount,
+ nsXPTCVariant* params);
+
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ return _NS_InvokeByIndex(that, methodIndex, paramCount, params);
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp
new file mode 100644
index 0000000000..c0c3e510fa
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp
@@ -0,0 +1,148 @@
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xptcprivate.h"
+
+#if _HPUX
+#error "This code is for HP-PA RISC 32 bit mode only"
+#endif
+
+#include <alloca.h>
+
+typedef unsigned nsXPCVariant;
+
+extern "C" int32_t
+invoke_count_bytes(nsISupports* that, const uint32_t methodIndex,
+ const uint32_t paramCount, const nsXPTCVariant* s)
+{
+ int32_t result = 4; /* variant records do not include self pointer */
+
+ /* counts the number of bytes required by the argument stack,
+ 64 bit integer, and double requires 8 bytes. All else requires
+ 4 bytes.
+ */
+
+ {
+ uint32_t indx;
+ for (indx = paramCount; indx > 0; --indx, ++s)
+ {
+ if (! s->IsPtrData())
+ {
+ if (s->type == nsXPTType::T_I64 || s->type == nsXPTType::T_U64 ||
+ s->type == nsXPTType::T_DOUBLE)
+ {
+ /* 64 bit integer and double aligned on 8 byte boundaries */
+ result += (result & 4) + 8;
+ continue;
+ }
+ }
+ result += 4; /* all other cases use 4 bytes */
+ }
+ }
+ result -= 72; /* existing stack buffer is 72 bytes */
+ if (result < 0)
+ return 0;
+ {
+ /* round up to 64 bytes boundary */
+ int32_t remainder = result & 63;
+ return (remainder == 0) ? result : (result + 64 - remainder);
+ }
+}
+
+extern "C" uint32_t
+invoke_copy_to_stack(uint32_t* d,
+ const uint32_t paramCount, nsXPTCVariant* s)
+{
+
+ typedef struct
+ {
+ uint32_t hi;
+ uint32_t lo;
+ } DU;
+
+ uint32_t* dest = d;
+ nsXPTCVariant* source = s;
+ /* we clobber param vars by copying stuff on stack, have to use local var */
+
+ uint32_t floatflags = 0;
+ /* flag indicating which floating point registers to load */
+
+ uint32_t regwords = 1; /* register 26 is reserved for ptr to 'that' */
+ uint32_t indx;
+
+ for (indx = paramCount; indx > 0; --indx, --dest, ++source)
+ {
+ if (source->IsPtrData())
+ {
+ *((void**) dest) = source->ptr;
+ ++regwords;
+ continue;
+ }
+ switch (source->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) dest) = source->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) dest) = source->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) dest) = source->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ if (regwords & 1)
+ {
+ /* align on double word boundary */
+ --dest;
+ ++regwords;
+ }
+ *((uint32_t*) dest) = ((DU *) source)->lo;
+ *((uint32_t*) --dest) = ((DU *) source)->hi;
+ /* big endian - hi word in low addr */
+ regwords += 2;
+ continue;
+ case nsXPTType::T_DOUBLE :
+ if (regwords & 1)
+ {
+ /* align on double word boundary */
+ --dest;
+ ++regwords;
+ }
+ switch (regwords) /* load double precision float register */
+ {
+ case 2:
+ floatflags |= 1;
+ }
+ *((uint32_t*) dest) = ((DU *) source)->lo;
+ *((uint32_t*) --dest) = ((DU *) source)->hi;
+ /* big endian - hi word in low addr */
+ regwords += 2;
+ continue;
+ case nsXPTType::T_FLOAT :
+ switch (regwords) /* load single precision float register */
+ {
+ case 1:
+ floatflags |= 2;
+ break;
+ case 2:
+ floatflags |= 4;
+ break;
+ case 3:
+ floatflags |= 8;
+ }
+ *((float*) dest) = source->val.f;
+ break;
+ case nsXPTType::T_U8 : *((uint32_t*) (dest)) = source->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*) (dest)) = source->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*) (dest)) = source->val.u32; break;
+ case nsXPTType::T_BOOL : *((uint32_t*) (dest)) = source->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*) (dest)) = source->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32_t*) (dest)) = source->val.wc; break;
+
+ default:
+ // all the others are plain pointer types
+ *((void**) dest) = source->val.p;
+ }
+ ++regwords;
+ }
+ return floatflags;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp
new file mode 100644
index 0000000000..f7673bb29d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp
@@ -0,0 +1,140 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+#include "xptcprivate.h"
+
+// The purpose of NS_InvokeByIndex() is to map a platform
+// independent call to the platform ABI. To do that,
+// NS_InvokeByIndex() has to determine the method to call via vtable
+// access. The parameters for the method are read from the
+// nsXPTCVariant* and prepared for the native ABI.
+//
+// Prior to POWER8, all 64-bit Power ISA systems used ELF v1 ABI, found
+// here:
+// https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html
+// and in particular:
+// https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-CALL
+// Little-endian ppc64le, however, uses ELF v2 ABI, which is here:
+// http://openpowerfoundation.org/wp-content/uploads/resources/leabi/leabi-20170510.pdf
+// and in particular section 2.2, page 22. However, most big-endian ppc64
+// systems still use ELF v1, so this file should support both.
+
+// 7 integral parameters are passed in registers, not including |this|
+// (i.e., r3-r10, with r3 being |this|).
+const uint32_t GPR_COUNT = 7;
+
+// 13 floating point parameters are passed in registers, either single or
+// double precision (i.e., f1-f13).
+const uint32_t FPR_COUNT = 13;
+
+// Both ABIs use the same register assignment strategy, as per this
+// example from V1 ABI section 3.2.3 and V2 ABI section 2.2.3.2 [page 43]:
+//
+// typedef struct {
+// int a;
+// double dd;
+// } sparm;
+// sparm s, t;
+// int c, d, e;
+// long double ld;
+// double ff, gg, hh;
+//
+// x = func(c, ff, d, ld, s, gg, t, e, hh);
+//
+// Parameter Register Offset in parameter save area
+// c r3 0-7 (not stored in parameter save area)
+// ff f1 8-15 (not stored)
+// d r5 16-23 (not stored)
+// ld f2,f3 24-39 (not stored)
+// s r8,r9 40-55 (not stored)
+// gg f4 56-63 (not stored)
+// t (none) 64-79 (stored in parameter save area)
+// e (none) 80-87 (stored)
+// hh f5 88-95 (not stored)
+//
+// i.e., each successive FPR usage skips a GPR, but not the other way around.
+
+extern "C" void invoke_copy_to_stack(uint64_t* gpregs, double* fpregs,
+ uint32_t paramCount, nsXPTCVariant* s,
+ uint64_t* d)
+{
+ uint32_t nr_gpr = 0u;
+ uint32_t nr_fpr = 0u;
+ uint64_t value = 0u;
+
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (s->IsIndirect())
+ value = (uint64_t) &s->val;
+ else {
+ switch (s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: value = s->val.i8; break;
+ case nsXPTType::T_I16: value = s->val.i16; break;
+ case nsXPTType::T_I32: value = s->val.i32; break;
+ case nsXPTType::T_I64: value = s->val.i64; break;
+ case nsXPTType::T_U8: value = s->val.u8; break;
+ case nsXPTType::T_U16: value = s->val.u16; break;
+ case nsXPTType::T_U32: value = s->val.u32; break;
+ case nsXPTType::T_U64: value = s->val.u64; break;
+ case nsXPTType::T_BOOL: value = s->val.b; break;
+ case nsXPTType::T_CHAR: value = s->val.c; break;
+ case nsXPTType::T_WCHAR: value = s->val.wc; break;
+ default: value = (uint64_t) s->val.p; break;
+ }
+ }
+
+ if (!s->IsIndirect() && s->type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT) {
+ fpregs[nr_fpr++] = s->val.d;
+ // Even if we have enough FPRs, still skip space in
+ // the parameter area if we ran out of placeholder GPRs.
+ if (nr_gpr < GPR_COUNT) {
+ nr_gpr++;
+ } else {
+ d++;
+ }
+ } else {
+ *((double *)d) = s->val.d;
+ d++;
+ }
+ }
+ else if (!s->IsIndirect() && s->type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT) {
+ // Single-precision floats are passed in FPRs too.
+ fpregs[nr_fpr++] = s->val.f;
+ if (nr_gpr < GPR_COUNT) {
+ nr_gpr++;
+ } else {
+ d++;
+ }
+ } else {
+#ifdef __LITTLE_ENDIAN__
+ *((float *)d) = s->val.f;
+#else
+ // Big endian needs adjustment to point to the least
+ // significant word.
+ float* p = (float*)d;
+ p++;
+ *p = s->val.f;
+#endif
+ d++;
+ }
+ }
+ else {
+ if (nr_gpr < GPR_COUNT) {
+ gpregs[nr_gpr++] = value;
+ } else {
+ *d++ = value;
+ }
+ }
+ }
+}
+
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, uint32_t paramCount,
+ nsXPTCVariant* params);
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp
new file mode 100644
index 0000000000..d894224539
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp
@@ -0,0 +1,73 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#ifndef AIX
+#error "This code is for PowerPC only"
+#endif
+
+extern "C" void
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s, double *fprData)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint32_t *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32_t l_paramCount = paramCount, fpCount = 0;
+ double *l_fprData = fprData;
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if(l_s->IsPtrData())
+ {
+ *((void**)l_d) = l_s->ptr;
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ *((uint32_t*) l_d++) = ((DU *)l_s)->hi;
+ *((uint32_t*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_DOUBLE :
+ *((uint32_t*) l_d++) = ((DU *)l_s)->hi;
+ *((uint32_t*) l_d) = ((DU *)l_s)->lo;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.d;
+ break;
+ case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT :
+ *((float*) l_d) = l_s->val.f;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.f;
+ break;
+ case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp
new file mode 100644
index 0000000000..588f1266c0
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp
@@ -0,0 +1,62 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#ifdef _AIX
+
+extern "C" void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s, double *fprData)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint64_t *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32_t l_paramCount = paramCount, fpCount = 0;
+ double *l_fprData = fprData;
+
+ for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if(l_s->IsPtrData())
+ {
+ *l_d = (uint64_t)l_s->ptr;
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8: *l_d = (uint64_t)l_s->val.i8; break;
+ case nsXPTType::T_I16: *l_d = (uint64_t)l_s->val.i16; break;
+ case nsXPTType::T_I32: *l_d = (uint64_t)l_s->val.i32; break;
+ case nsXPTType::T_I64: *l_d = (uint64_t)l_s->val.i64; break;
+ case nsXPTType::T_U8: *l_d = (uint64_t)l_s->val.u8; break;
+ case nsXPTType::T_U16: *l_d = (uint64_t)l_s->val.u16; break;
+ case nsXPTType::T_U32: *l_d = (uint64_t)l_s->val.u32; break;
+ case nsXPTType::T_U64: *l_d = (uint64_t)l_s->val.u64; break;
+ case nsXPTType::T_BOOL: *l_d = (uint64_t)l_s->val.b; break;
+ case nsXPTType::T_CHAR: *l_d = (uint64_t)l_s->val.c; break;
+ case nsXPTType::T_WCHAR: *l_d = (uint64_t)l_s->val.wc; break;
+
+ case nsXPTType::T_DOUBLE:
+ *((double*)l_d) = l_s->val.d;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.d;
+ break;
+ case nsXPTType::T_FLOAT:
+ *((float*)l_d) = l_s->val.f;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.f;
+ break;
+ default:
+ // all the others are plain pointer types
+ *l_d = (uint64_t)l_s->val.p;
+ break;
+ }
+ }
+}
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp
new file mode 100644
index 0000000000..6af3608357
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp
@@ -0,0 +1,128 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+// The purpose of NS_InvokeByIndex() is to map a platform
+// indepenpent call to the platform ABI. To do that,
+// NS_InvokeByIndex() has to determine the method to call via vtable
+// access. The parameters for the method are read from the
+// nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC
+// ABI this means that the first 8 integral and floating point
+// parameters are passed in registers.
+
+#include "xptcprivate.h"
+
+// 8 integral parameters are passed in registers
+#define GPR_COUNT 8
+
+// With hardfloat support 8 floating point parameters are passed in registers,
+// floats are promoted to doubles when passed in registers
+// In Softfloat mode, everything is handled via gprs
+#ifndef __NO_FPRS__
+#define FPR_COUNT 8
+#endif
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ return uint32_t(((paramCount * 2) + 3) & ~3);
+}
+
+extern "C" void
+invoke_copy_to_stack(uint32_t* d,
+ uint32_t paramCount,
+ nsXPTCVariant* s,
+ uint32_t* gpregs,
+ double* fpregs)
+{
+ uint32_t gpr = 1; // skip one GP reg for 'that'
+#ifndef __NO_FPRS__
+ uint32_t fpr = 0;
+#endif
+ uint32_t tempu32;
+ uint64_t tempu64;
+
+ for(uint32_t i = 0; i < paramCount; i++, s++) {
+ if(s->IsPtrData()) {
+ if(s->type == nsXPTType::T_JSVAL)
+ tempu32 = (uint32_t) &s->ptr;
+ else
+ tempu32 = (uint32_t) s->ptr;
+ }
+ else {
+ switch(s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: tempu32 = s->val.i8; break;
+ case nsXPTType::T_I16: tempu32 = s->val.i16; break;
+ case nsXPTType::T_I32: tempu32 = s->val.i32; break;
+ case nsXPTType::T_I64: tempu64 = s->val.i64; break;
+ case nsXPTType::T_U8: tempu32 = s->val.u8; break;
+ case nsXPTType::T_U16: tempu32 = s->val.u16; break;
+ case nsXPTType::T_U32: tempu32 = s->val.u32; break;
+ case nsXPTType::T_U64: tempu64 = s->val.u64; break;
+ case nsXPTType::T_BOOL: tempu32 = s->val.b; break;
+ case nsXPTType::T_CHAR: tempu32 = s->val.c; break;
+ case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break;
+ default: tempu32 = (uint32_t) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+#ifndef __NO_FPRS__
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.d;
+#else
+ if (gpr & 1)
+ gpr++;
+ if ((gpr + 1) < GPR_COUNT) {
+ *((double*) &gpregs[gpr]) = s->val.d;
+ gpr += 2;
+ }
+#endif
+ else {
+ if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack
+ *((double*) d) = s->val.d;
+ d += 2;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+#ifndef __NO_FPRS__
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles
+#else
+ if (gpr < GPR_COUNT)
+ *((float*) &gpregs[gpr++]) = s->val.f;
+#endif
+ else
+ *((float*) d++) = s->val.f;
+ }
+ else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64
+ || s->type == nsXPTType::T_U64)) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((gpr + 1) < GPR_COUNT) {
+ *((uint64_t*) &gpregs[gpr]) = tempu64;
+ gpr += 2;
+ }
+ else {
+ if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack
+ *((uint64_t*) d) = tempu64;
+ d += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ gpregs[gpr++] = tempu32;
+ else
+ *d++ = tempu32;
+ }
+
+ }
+}
+
+extern "C"
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp
new file mode 100644
index 0000000000..5c4f8b49fe
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp
@@ -0,0 +1,109 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+// The purpose of NS_InvokeByIndex() is to map a platform
+// indepenpent call to the platform ABI. To do that,
+// NS_InvokeByIndex() has to determine the method to call via vtable
+// access. The parameters for the method are read from the
+// nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC
+// ABI this means that the first 8 integral and floating point
+// parameters are passed in registers.
+
+#include "xptcprivate.h"
+
+// 8 integral parameters are passed in registers
+#define GPR_COUNT 8
+
+// 8 floating point parameters are passed in registers, floats are
+// promoted to doubles when passed in registers
+#define FPR_COUNT 8
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ return uint32_t(((paramCount * 2) + 3) & ~3);
+}
+
+extern "C" void
+invoke_copy_to_stack(uint32_t* d,
+ uint32_t paramCount,
+ nsXPTCVariant* s,
+ uint32_t* gpregs,
+ double* fpregs)
+{
+ uint32_t gpr = 1; // skip one GP reg for 'that'
+ uint32_t fpr = 0;
+ uint32_t tempu32;
+ uint64_t tempu64;
+
+ for(uint32_t i = 0; i < paramCount; i++, s++) {
+ if(s->IsPtrData()) {
+ if(s->type == nsXPTType::T_JSVAL)
+ tempu32 = (uint32_t) &(s->ptr);
+ else
+ tempu32 = (uint32_t) s->ptr;
+ } else {
+ switch(s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: tempu32 = s->val.i8; break;
+ case nsXPTType::T_I16: tempu32 = s->val.i16; break;
+ case nsXPTType::T_I32: tempu32 = s->val.i32; break;
+ case nsXPTType::T_I64: tempu64 = s->val.i64; break;
+ case nsXPTType::T_U8: tempu32 = s->val.u8; break;
+ case nsXPTType::T_U16: tempu32 = s->val.u16; break;
+ case nsXPTType::T_U32: tempu32 = s->val.u32; break;
+ case nsXPTType::T_U64: tempu64 = s->val.u64; break;
+ case nsXPTType::T_BOOL: tempu32 = s->val.b; break;
+ case nsXPTType::T_CHAR: tempu32 = s->val.c; break;
+ case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break;
+ default: tempu32 = (uint32_t) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.d;
+ else {
+ if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack
+ *((double*) d) = s->val.d;
+ d += 2;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles
+ else
+ *((float*) d++) = s->val.f;
+ }
+ else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64
+ || s->type == nsXPTType::T_U64)) {
+ if ((gpr + 1) < GPR_COUNT) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ *((uint64_t*) &gpregs[gpr]) = tempu64;
+ gpr += 2;
+ }
+ else {
+ if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack
+ *((uint64_t*) d) = tempu64;
+ d += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ gpregs[gpr++] = tempu32;
+ else
+ *d++ = tempu32;
+ }
+
+ }
+}
+
+extern "C"
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp
new file mode 100644
index 0000000000..4a434c426b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp
@@ -0,0 +1,113 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t result = 0;
+ /* fprintf(stderr,"invoke_count_words(%d,%p)\n",paramCount, s);*/
+
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+extern "C" void
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s, double *fprData)
+{
+ uint32_t fpCount = 0;
+
+ /* fprintf(stderr,"invoke_copy_to_stack(%p, %d, %p, %p)\n", d, paramCount, s, fprData);*/
+
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint32_t*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f;
+ if (fpCount < 13)
+ fprData[fpCount++] = s->val.f;
+ break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++;
+ if (fpCount < 13)
+ fprData[fpCount++] = s->val.d;
+ break;
+ case nsXPTType::T_BOOL : *((uint32_t*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((int32_t*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((uint32_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount,
+ nsXPTCVariant* params);
+
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ return _NS_InvokeByIndex(that, methodIndex, paramCount, params);
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_riscv64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_riscv64.cpp
new file mode 100644
index 0000000000..ddd6692156
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_riscv64.cpp
@@ -0,0 +1,106 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+#if defined(__riscv_float_abi_soft)
+# error "Not support soft float ABI"
+#endif
+
+#include "xptcprivate.h"
+
+extern "C" void invoke_copy_to_stack(uint64_t* gpregs, double* fpregs,
+ uint32_t paramCount, nsXPTCVariant* s,
+ uint64_t* d) {
+ static const uint32_t GPR_COUNT = 8;
+ static const uint32_t FPR_COUNT = 8;
+
+ uint32_t nr_gpr = 1; // skip one GPR register for "this"
+ uint32_t nr_fpr = 0;
+ uint64_t value = 0;
+
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (s->IsIndirect()) {
+ value = (uint64_t)&s->val;
+ } else {
+ switch (s->type) {
+ case nsXPTType::T_FLOAT:
+ break;
+ case nsXPTType::T_DOUBLE:
+ break;
+ case nsXPTType::T_I8:
+ value = s->val.i8;
+ break;
+ case nsXPTType::T_I16:
+ value = s->val.i16;
+ break;
+ case nsXPTType::T_I32:
+ value = s->val.i32;
+ break;
+ case nsXPTType::T_I64:
+ value = s->val.i64;
+ break;
+ case nsXPTType::T_U8:
+ value = s->val.u8;
+ break;
+ case nsXPTType::T_U16:
+ value = s->val.u16;
+ break;
+ case nsXPTType::T_U32:
+ value = s->val.u32;
+ break;
+ case nsXPTType::T_U64:
+ value = s->val.u64;
+ break;
+ case nsXPTType::T_BOOL:
+ value = s->val.b;
+ break;
+ case nsXPTType::T_CHAR:
+ value = s->val.c;
+ break;
+ case nsXPTType::T_WCHAR:
+ value = s->val.wc;
+ break;
+ default:
+ value = (uint64_t)s->val.p;
+ break;
+ }
+ }
+
+ if (!s->IsIndirect() && s->type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT) {
+ fpregs[nr_fpr++] = s->val.d;
+ } else {
+ *((double*)d) = s->val.d;
+ d++;
+ }
+ } else if (!s->IsIndirect() && s->type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT) {
+ // The value in %fa register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ fpregs[nr_fpr++] = s->val.d;
+ } else {
+ *((float*)d) = s->val.f;
+ d++;
+ }
+ } else {
+ if (nr_gpr < GPR_COUNT) {
+ gpregs[nr_gpr++] = value;
+ } else {
+ *d++ = value;
+ }
+ }
+ }
+}
+
+extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount,
+ nsXPTCVariant* params);
+
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, uint32_t paramCount,
+ nsXPTCVariant* params) {
+ return _NS_InvokeByIndex(that, methodIndex, paramCount, params);
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp
new file mode 100644
index 0000000000..aa90988a17
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+extern "C" uint64_t
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ /*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+ */
+ uint64_t *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint64_t l_paramCount = paramCount;
+ uint64_t regCount = 0; // return the number of registers to load from the stack
+
+ for(uint64_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+
+ if (l_s->IsIndirect())
+ {
+ *l_d = (uint64_t) &l_s->val;
+ continue;
+ }
+ switch (l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int64_t*)l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int64_t*)l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int64_t*)l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*)l_d) = l_s->val.i64; break;
+
+ case nsXPTType::T_U8 : *((uint64_t*)l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint64_t*)l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint64_t*)l_d) = l_s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)l_d) = l_s->val.u64; break;
+
+ /* in the case of floats, we want to put the bits in to the
+ 64bit space right justified... floats in the parameter array on
+ sparcv9 use odd numbered registers.. %f1, %f3, so we have to skip
+ the space that would be occupied by %f0, %f2, etc.
+ */
+ case nsXPTType::T_FLOAT : *(((float*)l_d) + 1) = l_s->val.f; break;
+ case nsXPTType::T_DOUBLE: *((double*)l_d) = l_s->val.d; break;
+ case nsXPTType::T_BOOL : *((int64_t*)l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint64_t*)l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int64_t*)l_d) = l_s->val.wc; break;
+
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+
+ return regCount;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp
new file mode 100644
index 0000000000..3ab0812622
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp
@@ -0,0 +1,130 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+/* solaris defines __sparc for workshop compilers and
+ linux defines __sparc__ */
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+typedef unsigned nsXPCVariant;
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t result = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ // nuts, I know there's a cooler way of doing this, but it's late
+ // now and it'll probably come to me in the morning.
+ if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment
+ return result;
+}
+
+extern "C" uint32_t
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint32_t *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32_t l_paramCount = paramCount;
+ uint32_t regCount = 0; // return the number of registers to load from the stack
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+ if(l_s->IsPtrData())
+ {
+ if(l_s->type == nsXPTType::T_JSVAL)
+ {
+ // On SPARC, we need to pass a pointer to HandleValue
+ *((void**)l_d) = &l_s->ptr;
+ } else
+ {
+ *((void**)l_d) = l_s->ptr;
+ }
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE : *((uint32_t*) l_d++) = ((DU *)l_s)->hi;
+ if (regCount < 5) regCount++;
+ *((uint32_t*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break;
+ case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+ return regCount;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp
new file mode 100644
index 0000000000..fb99c303f7
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp
@@ -0,0 +1,127 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+typedef unsigned nsXPCVariant;
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t result = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ // nuts, I know there's a cooler way of doing this, but it's late
+ // now and it'll probably come to me in the morning.
+ if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment
+ return result;
+}
+
+extern "C" uint32_t
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint32_t *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32_t l_paramCount = paramCount;
+ uint32_t regCount = 0; // return the number of registers to load from the stack
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+ if(l_s->IsPtrData())
+ {
+ if(l_s->type == nsXPTType::T_JSVAL)
+ {
+ // On SPARC, we need to pass a pointer to HandleValue
+ *((void**)l_d) = &l_s->ptr;
+ } else
+ {
+ *((void**)l_d) = l_s->ptr;
+ }
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE : *((uint32_t*) l_d++) = ((DU *)l_s)->hi;
+ if (regCount < 5) regCount++;
+ *((uint32_t*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break;
+ case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+ return regCount;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp
new file mode 100644
index 0000000000..3ab0812622
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp
@@ -0,0 +1,130 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+/* solaris defines __sparc for workshop compilers and
+ linux defines __sparc__ */
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+typedef unsigned nsXPCVariant;
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t result = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ // nuts, I know there's a cooler way of doing this, but it's late
+ // now and it'll probably come to me in the morning.
+ if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment
+ return result;
+}
+
+extern "C" uint32_t
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint32_t *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32_t l_paramCount = paramCount;
+ uint32_t regCount = 0; // return the number of registers to load from the stack
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+ if(l_s->IsPtrData())
+ {
+ if(l_s->type == nsXPTType::T_JSVAL)
+ {
+ // On SPARC, we need to pass a pointer to HandleValue
+ *((void**)l_d) = &l_s->ptr;
+ } else
+ {
+ *((void**)l_d) = l_s->ptr;
+ }
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE : *((uint32_t*) l_d++) = ((DU *)l_s)->hi;
+ if (regCount < 5) regCount++;
+ *((uint32_t*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break;
+ case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+ return regCount;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp
new file mode 100644
index 0000000000..ae034abf29
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp
@@ -0,0 +1,76 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+#include "xptcall.h"
+#include "xptinfo.h"
+
+// 6 integral parameters are passed in registers, but 1 is |this| which isn't
+// considered here.
+const uint32_t GPR_COUNT = 5;
+
+// 8 floating point parameters are passed in SSE registers
+const uint32_t FPR_COUNT = 8;
+
+extern "C" void
+InvokeCopyToStack(uint64_t * gpregs, double * fpregs,
+ uint32_t paramCount, nsXPTCVariant * s,
+ uint64_t* d)
+{
+ uint32_t nr_gpr = 0u;
+ uint32_t nr_fpr = 0u;
+ uint64_t value = 0u;
+
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (s->IsIndirect())
+ value = (uint64_t) &s->val;
+ else {
+ switch (s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: value = s->val.i8; break;
+ case nsXPTType::T_I16: value = s->val.i16; break;
+ case nsXPTType::T_I32: value = s->val.i32; break;
+ case nsXPTType::T_I64: value = s->val.i64; break;
+ case nsXPTType::T_U8: value = s->val.u8; break;
+ case nsXPTType::T_U16: value = s->val.u16; break;
+ case nsXPTType::T_U32: value = s->val.u32; break;
+ case nsXPTType::T_U64: value = s->val.u64; break;
+ case nsXPTType::T_BOOL: value = s->val.b; break;
+ case nsXPTType::T_CHAR: value = s->val.c; break;
+ case nsXPTType::T_WCHAR: value = s->val.wc; break;
+ default: value = (uint64_t) s->val.p; break;
+ }
+ }
+
+ if (!s->IsIndirect() && s->type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((double *)d) = s->val.d;
+ d++;
+ }
+ }
+ else if (!s->IsIndirect() && s->type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((float *)d) = s->val.f;
+ d++;
+ }
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ gpregs[nr_gpr++] = value;
+ else
+ *d++ = value;
+ }
+ }
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp
new file mode 100644
index 0000000000..d535557259
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp
@@ -0,0 +1,238 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xptcprivate.h"
+
+#ifndef __AARCH64EL__
+#error "Only little endian compatibility was tested"
+#endif
+
+template<typename T> void
+get_value_and_advance(T* aOutValue, void*& aStack) {
+#ifdef __APPLE__
+ const size_t aligned_size = sizeof(T);
+#else
+ const size_t aligned_size = 8;
+#endif
+ // Ensure the pointer is aligned for the type
+ uintptr_t addr = (reinterpret_cast<uintptr_t>(aStack) + aligned_size - 1) & ~(aligned_size - 1);
+ memcpy(aOutValue, reinterpret_cast<void*>(addr), sizeof(T));
+ aStack = reinterpret_cast<void*>(addr + aligned_size);
+}
+
+/*
+ * This is for AArch64 ABI
+ *
+ * When we're called, the "gp" registers are stored in gprData and
+ * the "fp" registers are stored in fprData. Each array has 8 regs
+ * but first reg in gprData is a placeholder for 'self'.
+ */
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, void* args,
+ uint64_t *gprData, double *fprData)
+{
+#define PARAM_GPR_COUNT 8
+#define PARAM_FPR_COUNT 8
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ uint32_t paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ void* ap = args;
+ uint32_t next_gpr = 1; // skip first arg which is 'self'
+ uint32_t next_fpr = 0;
+ for (uint32_t i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (next_gpr < PARAM_GPR_COUNT)
+ next_gpr++;
+ else {
+ void* value;
+ get_value_and_advance(&value, ap);
+ }
+ }
+
+ if (param.IsOut() || !type.IsArithmetic()) {
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.p = (void*)gprData[next_gpr++];
+ } else {
+ get_value_and_advance(&dp->val.p, ap);
+ }
+ continue;
+ }
+
+ switch (type) {
+ case nsXPTType::T_I8:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.i8 = (int8_t)gprData[next_gpr++];
+ } else {
+ get_value_and_advance(&dp->val.i8, ap);
+ }
+ break;
+
+ case nsXPTType::T_I16:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.i16 = (int16_t)gprData[next_gpr++];
+ } else {
+ get_value_and_advance(&dp->val.i16, ap);
+ }
+ break;
+
+ case nsXPTType::T_I32:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.i32 = (int32_t)gprData[next_gpr++];
+ } else {
+ get_value_and_advance(&dp->val.i32, ap);
+ }
+ break;
+
+ case nsXPTType::T_I64:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.i64 = (int64_t)gprData[next_gpr++];
+ } else {
+ get_value_and_advance(&dp->val.i64, ap);
+ }
+ break;
+
+ case nsXPTType::T_U8:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.u8 = (uint8_t)gprData[next_gpr++];
+ } else {
+ get_value_and_advance(&dp->val.u8, ap);
+ }
+ break;
+
+ case nsXPTType::T_U16:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.u16 = (uint16_t)gprData[next_gpr++];
+ } else {
+ get_value_and_advance(&dp->val.u16, ap);
+ }
+ break;
+
+ case nsXPTType::T_U32:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.u32 = (uint32_t)gprData[next_gpr++];
+ } else {
+ get_value_and_advance(&dp->val.u32, ap);
+ }
+ break;
+
+ case nsXPTType::T_U64:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.u64 = (uint64_t)gprData[next_gpr++];
+ } else {
+ get_value_and_advance(&dp->val.u64, ap);
+ }
+ break;
+
+ case nsXPTType::T_FLOAT:
+ if (next_fpr < PARAM_FPR_COUNT) {
+ memcpy(&dp->val.f, &fprData[next_fpr++], sizeof(dp->val.f));
+ } else {
+ get_value_and_advance(&dp->val.f, ap);
+ }
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ if (next_fpr < PARAM_FPR_COUNT) {
+ memcpy(&dp->val.d, &fprData[next_fpr++], sizeof(dp->val.d));
+ } else {
+ get_value_and_advance(&dp->val.d, ap);
+ }
+ break;
+
+ case nsXPTType::T_BOOL:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.b = (bool)(uint8_t)gprData[next_gpr++];
+ } else {
+ uint8_t value;
+ get_value_and_advance(&value, ap);
+ dp->val.b = (bool)value;
+ }
+ break;
+
+ case nsXPTType::T_CHAR:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.c = (char)gprData[next_gpr++];
+ } else {
+ get_value_and_advance(&dp->val.c, ap);
+ }
+ break;
+
+ case nsXPTType::T_WCHAR:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.wc = (wchar_t)gprData[next_gpr++];
+ } else {
+ get_value_and_advance(&dp->val.wc, ap);
+ }
+ break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+#ifdef __APPLE__
+#define GNU(str)
+#define UNDERSCORE "__"
+#else
+#define GNU(str) str
+#define UNDERSCORE "_"
+#endif
+
+// Load w17 with the constant 'n' and branch to SharedStub().
+# define STUB_ENTRY(n) \
+ __asm__ ( \
+ ".text\n\t" \
+ ".align 2\n\t" \
+ ".if "#n" < 10 \n\t" \
+ ".globl " UNDERSCORE "ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ GNU(".hidden _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t") \
+ GNU(".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n")\
+ "" UNDERSCORE "ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
+ ".elseif "#n" < 100 \n\t" \
+ ".globl " UNDERSCORE "ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ GNU(".hidden _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t") \
+ GNU(".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n")\
+ "" UNDERSCORE "ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ ".elseif "#n" < 1000 \n\t" \
+ ".globl " UNDERSCORE "ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ GNU(".hidden _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t") \
+ GNU(".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n")\
+ UNDERSCORE "ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
+ ".else \n\t" \
+ ".err \"stub number "#n" >= 1000 not yet supported\"\n" \
+ ".endif \n\t" \
+ "mov w17,#"#n" \n\t" \
+ "b SharedStub \n" \
+);
+
+#define SENTINEL_ENTRY(n) \
+ nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp
new file mode 100644
index 0000000000..248c658d68
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp
@@ -0,0 +1,178 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+/* Prototype specifies unmangled function name and disables unused warning */
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args)
+__asm__("PrepareAndDispatch") ATTRIBUTE_USED;
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args)
+{
+ const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ // args[0] to args[NUM_ARG_REGS] hold floating point register values
+ uint64_t* ap = args + NUM_ARG_REGS;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext)
+ ap++;
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = (int8_t) *ap; break;
+ case nsXPTType::T_I16 : dp->val.i16 = (int16_t) *ap; break;
+ case nsXPTType::T_I32 : dp->val.i32 = (int32_t) *ap; break;
+ case nsXPTType::T_I64 : dp->val.i64 = (int64_t) *ap; break;
+ case nsXPTType::T_U8 : dp->val.u8 = (uint8_t) *ap; break;
+ case nsXPTType::T_U16 : dp->val.u16 = (uint16_t) *ap; break;
+ case nsXPTType::T_U32 : dp->val.u32 = (uint32_t) *ap; break;
+ case nsXPTType::T_U64 : dp->val.u64 = (uint64_t) *ap; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // floats passed via registers are stored as doubles
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (uint64_t) args[i];
+ dp->val.f = (float) dp->val.d; // convert double to float
+ }
+ else
+ dp->val.u32 = (uint32_t) *ap;
+ break;
+ case nsXPTType::T_DOUBLE :
+ // doubles passed via registers are also stored
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap;
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = (bool) *ap; break;
+ case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break;
+ case nsXPTType::T_WCHAR : dp->val.wc = (char16_t) *ap; break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+/*
+ * SharedStub()
+ * Collects arguments and calls PrepareAndDispatch. The "methodIndex" is
+ * passed to this function via $1 to preserve the argument registers.
+ */
+__asm__(
+ "#### SharedStub ####\n"
+".text\n\t"
+ ".align 5\n\t"
+ ".ent SharedStub\n"
+"SharedStub:\n\t"
+ ".frame $30,96,$26,0\n\t"
+ ".mask 0x4000000,-96\n\t"
+ "ldgp $29,0($27)\n"
+"$SharedStub..ng:\n\t"
+ "subq $30,96,$30\n\t"
+ "stq $26,0($30)\n\t"
+ ".prologue 1\n\t"
+
+ /*
+ * Store arguments passed via registers to the stack.
+ * Floating point registers are stored as doubles and converted
+ * to floats in PrepareAndDispatch if necessary.
+ */
+ "stt $f17,16($30)\n\t" /* floating point registers */
+ "stt $f18,24($30)\n\t"
+ "stt $f19,32($30)\n\t"
+ "stt $f20,40($30)\n\t"
+ "stt $f21,48($30)\n\t"
+ "stq $17,56($30)\n\t" /* integer registers */
+ "stq $18,64($30)\n\t"
+ "stq $19,72($30)\n\t"
+ "stq $20,80($30)\n\t"
+ "stq $21,88($30)\n\t"
+
+ /*
+ * Call PrepareAndDispatch function.
+ */
+ "bis $1,$1,$17\n\t" /* pass "methodIndex" */
+ "addq $30,16,$18\n\t" /* pass "args" */
+ "bsr $26,$PrepareAndDispatch..ng\n\t"
+
+ "ldq $26,0($30)\n\t"
+ "addq $30,96,$30\n\t"
+ "ret $31,($26),1\n\t"
+ ".end SharedStub"
+ );
+
+/*
+ * nsresult nsXPTCStubBase::Stub##n()
+ * Sets register $1 to "methodIndex" and jumps to SharedStub.
+ */
+#define STUB_MANGLED_ENTRY(n, symbol) \
+ "#### Stub"#n" ####" "\n\t" \
+ ".text" "\n\t" \
+ ".align 5" "\n\t" \
+ ".globl " symbol "\n\t" \
+ ".ent " symbol "\n" \
+symbol ":" "\n\t" \
+ ".frame $30,0,$26,0" "\n\t" \
+ "ldgp $29,0($27)" "\n" \
+"$" symbol "..ng:" "\n\t" \
+ ".prologue 1" "\n\t" \
+ "lda $1,"#n "\n\t" \
+ "br $31,$SharedStub..ng" "\n\t" \
+ ".end " symbol
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".if "#n" < 10" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase5Stub"#n"Ev") "\n\t" \
+ ".elseif "#n" < 100" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase6Stub"#n"Ev") "\n\t" \
+ ".elseif "#n" < 1000" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase7Stub"#n"Ev") "\n\t" \
+ ".else" "\n\t" \
+ ".err \"Stub"#n" >= 1000 not yet supported.\"" "\n\t" \
+ ".endif" \
+ );
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp
new file mode 100644
index 0000000000..da855b7535
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp
@@ -0,0 +1,226 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if !defined(__arm__) && !(defined(LINUX) || defined(ANDROID) || defined(XP_DARWIN))
+#error "This code is for Linux/iOS ARM only. Please check if it works for you, too.\nDepends strongly on gcc behaviour."
+#endif
+
+#ifdef __ARM_EABI__
+#define DOUBLEWORD_ALIGN(p) ((uint32_t *)((((uint32_t)(p)) + 7) & 0xfffffff8))
+#else
+#define DOUBLEWORD_ALIGN(p) (p)
+#endif
+
+// Apple's iOS toolchain is lame.
+#ifdef __APPLE__
+#define GNU(str)
+#define APPLE(str) str
+#define UNDERSCORE "__"
+#else
+#define GNU(str) str
+#define APPLE(str)
+#define UNDERSCORE "_"
+#endif
+
+#ifdef __thumb__
+#define THUMB_FUNC ".thumb_func\n"
+#else
+#define THUMB_FUNC
+#endif
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext)
+ ap++;
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_I64 : ap = DOUBLEWORD_ALIGN(ap);
+ dp->val.i64 = *((int64_t*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U64 : ap = DOUBLEWORD_ALIGN(ap);
+ dp->val.u64 = *((uint64_t*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : ap = DOUBLEWORD_ALIGN(ap);
+ dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+/*
+ * This is our shared stub.
+ *
+ * r0 = Self.
+ *
+ * The Rules:
+ * We pass an (undefined) number of arguments into this function.
+ * The first 3 C++ arguments are in r1 - r3, the rest are built
+ * by the calling function on the stack.
+ *
+ * We are allowed to corrupt r0 - r3, ip, and lr.
+ *
+ * Other Info:
+ * We pass the stub number in using `ip'.
+ *
+ * Implementation:
+ * - We save r1 to r3 inclusive onto the stack, which will be
+ * immediately below the caller saved arguments.
+ * - setup r2 (PrepareAndDispatch's args pointer) to point at
+ * the base of all these arguments
+ * - Save LR (for the return address)
+ * - Set r1 (PrepareAndDispatch's methodindex argument) from ip
+ * - r0 is passed through (self)
+ * - Call PrepareAndDispatch
+ * - When the call returns, we return by loading the PC off the
+ * stack, and undoing the stack (one instruction)!
+ *
+ */
+__asm__ ("\n"
+ GNU(".text\n")
+ APPLE(".section __TEXT,__text\n")
+ THUMB_FUNC
+ ".align 2\n"
+ "SharedStub:\n"
+ GNU(".fnstart\n")
+ GNU(".cfi_startproc\n")
+ "stmfd sp!, {r1, r2, r3}\n"
+ GNU(".save {r1, r2, r3}\n")
+ GNU(".cfi_def_cfa_offset 12\n")
+ GNU(".cfi_offset r3, -4\n")
+ GNU(".cfi_offset r2, -8\n")
+ GNU(".cfi_offset r1, -12\n")
+ "mov r2, sp\n"
+ "str lr, [sp, #-4]!\n"
+ GNU(".save {lr}\n")
+ GNU(".cfi_def_cfa_offset 16\n")
+ GNU(".cfi_offset lr, -16\n")
+ "mov r1, ip\n"
+ "bl PrepareAndDispatch\n"
+ "ldr pc, [sp], #16\n"
+ GNU(".cfi_endproc\n")
+ GNU(".fnend"));
+
+/*
+ * Create sets of stubs to call the SharedStub.
+ * We don't touch the stack here, nor any registers, other than IP.
+ * IP is defined to be corruptable by a called function, so we are
+ * safe to use it.
+ *
+ * This will work with or without optimisation.
+ */
+
+/*
+ * Note : As G++3 ABI contains the length of the functionname in the
+ * mangled name, it is difficult to get a generic assembler mechanism like
+ * in the G++ 2.95 case.
+ * Create names would be like :
+ * _ZN14nsXPTCStubBase5Stub9Ev
+ * _ZN14nsXPTCStubBase6Stub13Ev
+ * _ZN14nsXPTCStubBase7Stub144Ev
+ * Use the assembler directives to get the names right...
+ */
+
+#define STUB_ENTRY(n) \
+ __asm__( \
+ GNU(".section \".text\"\n") \
+ APPLE(".section __TEXT,__text\n") \
+" .align 2\n" \
+" .if ("#n" - 10) < 0\n" \
+" .globl " UNDERSCORE "ZN14nsXPTCStubBase5Stub"#n"Ev\n" \
+ THUMB_FUNC \
+ GNU(".type _ZN14nsXPTCStubBase5Stub"#n"Ev,#function\n") \
+UNDERSCORE "ZN14nsXPTCStubBase5Stub"#n"Ev:\n" \
+" .else\n" \
+" .if ("#n" - 100) < 0\n" \
+" .globl " UNDERSCORE "ZN14nsXPTCStubBase6Stub"#n"Ev\n" \
+ THUMB_FUNC \
+ GNU(".type _ZN14nsXPTCStubBase6Stub"#n"Ev,#function\n") \
+UNDERSCORE "ZN14nsXPTCStubBase6Stub"#n"Ev:\n" \
+" .else\n" \
+" .if ("#n" - 1000) < 0\n" \
+" .globl " UNDERSCORE "ZN14nsXPTCStubBase7Stub"#n"Ev\n" \
+ THUMB_FUNC \
+ GNU(".type _ZN14nsXPTCStubBase7Stub"#n"Ev,#function\n") \
+UNDERSCORE "ZN14nsXPTCStubBase7Stub"#n"Ev:\n" \
+" .else\n" \
+" .err \"stub number "#n"> 1000 not yet supported\"\n" \
+" .endif\n" \
+" .endif\n" \
+" .endif\n" \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t");
+
+#if 0
+/*
+ * This part is left in as comment : this is how the method definition
+ * should look like.
+ */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n () \
+{ \
+ __asm__ ( \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t"); \
+ return 0; /* avoid warnings */ \
+}
+#endif
+
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp
new file mode 100644
index 0000000000..be7a36e948
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp
@@ -0,0 +1,99 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTInterfaceInfo* iface_info = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+/*
+ * These stubs move just move the values passed in registers onto the stack,
+ * so they are contiguous with values passed on the stack, and then calls
+ * PrepareAndDispatch() to do the dirty work.
+ */
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".global _Stub"#n"__14nsXPTCStubBase\n\t" \
+"_Stub"#n"__14nsXPTCStubBase:\n\t" \
+ "stmfd sp!, {r1, r2, r3} \n\t" \
+ "mov ip, sp \n\t" \
+ "stmfd sp!, {fp, ip, lr, pc} \n\t" \
+ "sub fp, ip, #4 \n\t" \
+ "mov r1, #"#n" \n\t" /* = methodIndex */ \
+ "add r2, sp, #16 \n\t" \
+ "bl _PrepareAndDispatch__FP14nsXPTCStubBaseUiPUi \n\t" \
+ "ldmea fp, {fp, sp, lr} \n\t" \
+ "add sp, sp, #12 \n\t" \
+ "mov pc, lr \n\t" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp
new file mode 100644
index 0000000000..c0fb0df7d4
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp
@@ -0,0 +1,194 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#ifdef __GNUC__
+/* This tells gcc3.4+ not to optimize away symbols.
+ * @see http://gcc.gnu.org/gcc-3.4/changes.html
+ */
+#define DONT_DROP_OR_WARN __attribute__((used))
+#else
+/* This tells older gccs not to warn about unused vairables.
+ * @see http://docs.freebsd.org/info/gcc/gcc.info.Variable_Attributes.html
+ */
+#define DONT_DROP_OR_WARN __attribute__((unused))
+#endif
+
+/* Specify explicitly a symbol for this function, don't try to guess the c++ mangled symbol. */
+static nsresult PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) asm("_PrepareAndDispatch")
+DONT_DROP_OR_WARN;
+
+static nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext)
+ ap++;
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+/*
+ * This is our shared stub.
+ *
+ * r0 = Self.
+ *
+ * The Rules:
+ * We pass an (undefined) number of arguments into this function.
+ * The first 3 C++ arguments are in r1 - r3, the rest are built
+ * by the calling function on the stack.
+ *
+ * We are allowed to corrupt r0 - r3, ip, and lr.
+ *
+ * Other Info:
+ * We pass the stub number in using `ip'.
+ *
+ * Implementation:
+ * - We save r1 to r3 inclusive onto the stack, which will be
+ * immediately below the caller saved arguments.
+ * - setup r2 (PrepareAndDispatch's args pointer) to point at
+ * the base of all these arguments
+ * - Save LR (for the return address)
+ * - Set r1 (PrepareAndDispatch's methodindex argument) from ip
+ * - r0 is passed through (self)
+ * - Call PrepareAndDispatch
+ * - When the call returns, we return by loading the PC off the
+ * stack, and undoing the stack (one instruction)!
+ *
+ */
+__asm__ ("\n\
+ .text \n\
+ .align 2 \n\
+SharedStub: \n\
+ stmfd sp!, {r1, r2, r3} \n\
+ mov r2, sp \n\
+ str lr, [sp, #-4]! \n\
+ mov r1, ip \n\
+ bl _PrepareAndDispatch \n\
+ ldr pc, [sp], #16");
+
+/*
+ * Create sets of stubs to call the SharedStub.
+ * We don't touch the stack here, nor any registers, other than IP.
+ * IP is defined to be corruptable by a called function, so we are
+ * safe to use it.
+ *
+ * This will work with or without optimisation.
+ */
+
+/*
+ * Note : As G++3 ABI contains the length of the functionname in the
+ * mangled name, it is difficult to get a generic assembler mechanism like
+ * in the G++ 2.95 case.
+ * Create names would be like :
+ * _ZN14nsXPTCStubBase5Stub9Ev
+ * _ZN14nsXPTCStubBase6Stub13Ev
+ * _ZN14nsXPTCStubBase7Stub144Ev
+ * Use the assembler directives to get the names right...
+ */
+
+#define STUB_ENTRY(n) \
+ __asm__( \
+ ".section \".text\"\n" \
+" .align 2\n" \
+" .iflt ("#n" - 10)\n" \
+" .globl _ZN14nsXPTCStubBase5Stub"#n"Ev\n" \
+" .type _ZN14nsXPTCStubBase5Stub"#n"Ev,#function\n" \
+"_ZN14nsXPTCStubBase5Stub"#n"Ev:\n" \
+" .else\n" \
+" .iflt ("#n" - 100)\n" \
+" .globl _ZN14nsXPTCStubBase6Stub"#n"Ev\n" \
+" .type _ZN14nsXPTCStubBase6Stub"#n"Ev,#function\n" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev:\n" \
+" .else\n" \
+" .iflt ("#n" - 1000)\n" \
+" .globl _ZN14nsXPTCStubBase7Stub"#n"Ev\n" \
+" .type _ZN14nsXPTCStubBase7Stub"#n"Ev,#function\n" \
+"_ZN14nsXPTCStubBase7Stub"#n"Ev:\n" \
+" .else\n" \
+" .err \"stub number "#n"> 1000 not yet supported\"\n" \
+" .endif\n" \
+" .endif\n" \
+" .endif\n" \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t");
+
+#if 0
+/*
+ * This part is left in as comment : this is how the method definition
+ * should look like.
+ */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n () \
+{ \
+ __asm__ ( \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t"); \
+ return 0; /* avoid warnings */ \
+}
+#endif
+
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.S
new file mode 100644
index 0000000000..f2394aa316
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.S
@@ -0,0 +1,62 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifdef __APPLE__
+#define SYM(x) _ ## x
+#else
+#define SYM(x) x
+#endif
+
+ .set NGPREGS,8
+ .set NFPREGS,8
+
+ .text
+ .align 2
+ .globl SharedStub
+#ifndef __APPLE__
+ .hidden SharedStub
+ .type SharedStub,@function
+#endif
+SharedStub:
+ .cfi_startproc
+ stp x29, x30, [sp,#-16]!
+ .cfi_adjust_cfa_offset 16
+ .cfi_rel_offset x29, 0
+ .cfi_rel_offset x30, 8
+ mov x29, sp
+ .cfi_def_cfa_register x29
+
+ sub sp, sp, #8*(NGPREGS+NFPREGS)
+ stp x0, x1, [sp, #64+(0*8)]
+ stp x2, x3, [sp, #64+(2*8)]
+ stp x4, x5, [sp, #64+(4*8)]
+ stp x6, x7, [sp, #64+(6*8)]
+ stp d0, d1, [sp, #(0*8)]
+ stp d2, d3, [sp, #(2*8)]
+ stp d4, d5, [sp, #(4*8)]
+ stp d6, d7, [sp, #(6*8)]
+
+ # methodIndex passed from stub
+ mov w1, w17
+
+ add x2, sp, #16+(8*(NGPREGS+NFPREGS))
+ add x3, sp, #8*NFPREGS
+ add x4, sp, #0
+
+ bl SYM(PrepareAndDispatch)
+
+ add sp, sp, #8*(NGPREGS+NFPREGS)
+ .cfi_def_cfa_register sp
+ ldp x29, x30, [sp],#16
+ .cfi_adjust_cfa_offset -16
+ .cfi_restore x29
+ .cfi_restore x30
+ ret
+ .cfi_endproc
+
+#ifndef __APPLE__
+ .size SharedStub, . - SharedStub
+
+ .section .note.GNU-stack, "", @progbits
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s
new file mode 100644
index 0000000000..720dd6cc71
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s
@@ -0,0 +1,123 @@
+
+// Select C numeric constant
+ .radix C
+ .psr abi32
+ .psr msb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'SharedStub'
+ .proc SharedStub
+// manual bundling
+ .explicit
+
+ .global PrepareAndDispatch
+// .exclass PrepareAndDispatch, @fullyvisible
+ .type PrepareAndDispatch,@function
+
+SharedStub::
+// 10 arguments, first 8 are the input arguments of previous
+// function call. The 9th one is methodIndex and the 10th is the
+// pointer to the remaining input arguments. The last two arguments
+// are passed in memory.
+ .prologue
+ .save ar.pfs , r41
+// allocate 8 input args, 4 local args, and 5 output args
+ alloc r41 = ar.pfs, 8, 4, 5, 0 // M
+ .save rp, r40
+ mov r40 = rp // I
+ addp4 out4 = 28, sp ;; // I
+
+ .save ar.unat, r42
+ mov r42 = ar.unat // M
+ .fframe 144
+ add sp = -144, sp // A
+// unwind table already knows gp, don't need to specify anything
+ add r43 = 0, gp ;; // A
+
+// We have possible 8 integer registers and 8 float registers that could
+// be arguments. We also have a stack region from the previous
+// stack frame that may hold some stack arguments.
+// We need to write the integer registers to a memory region, write
+// the float registers to a memory region (making sure we don't step
+// on NAT while touching the registers). We also mark the memory
+// address of the stack arguments.
+// We then call PrepareAndDispatch() specifying the three memory
+// region pointers.
+
+
+ .body
+ add out0 = 0, in0 // A move self ptr
+// 144 bytes = 16 byte stack header + 64 byte int space + 64 byte float space
+// methodIndex is at 144 + 16 bytes away from current sp
+// (current frame + previous frame header)
+ ld4 out4 = [out4] // A restarg address
+ add r11 = 160, sp ;; // A address of methodIndex
+
+ ld8 out1 = [r11] // M load methodIndex
+// sp + 16 is the start of intargs
+ add out2 = 16, sp // A address of intargs
+// the intargs take up 64 bytes, so sp + 16 + 64 is the start of floatargs
+ add out3 = 80, sp ;; // A address of floatargs
+
+ add r11 = 0, out2 ;; // A
+ st8.spill [r11] = in1, 8 // M
+ add r10 = 0, out3 ;; // A
+
+ st8.spill [r11] = in2, 8 ;; // M
+ st8.spill [r11] = in3, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in4, 8 ;; // M
+ st8.spill [r11] = in5, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in6, 8 ;; // M
+ st8.spill [r11] = in7 // M
+ fclass.nm p14,p15 = f8,@nat ;; // F
+
+(p14) stfd [r10] = f8, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 = f9,@nat ;; // F
+
+(p12) stfd [r10] = f9, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f10,@nat ;; // F
+
+(p14) stfd [r10] = f10, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f11,@nat ;; // F
+
+(p12) stfd [r10] = f11, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f12,@nat ;; // F
+
+(p14) stfd [r10] = f12, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f13,@nat ;; // F
+
+(p12) stfd [r10] = f13, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f14,@nat ;; // F
+
+(p14) stfd [r10] = f14, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f15,@nat ;; // F
+
+(p12) stfd [r10] = f15, 8 // M
+(p13) add r10 = 8, r10 // A
+
+// branch to PrepareAndDispatch
+ br.call.dptk.few rp = PrepareAndDispatch ;; // B
+
+// epilog
+ mov ar.unat = r42 // M
+ mov ar.pfs = r41 // I
+ mov rp = r40 ;; // I
+
+ add gp = 0, r43 // A
+ add sp = 144, sp // A
+ br.ret.dptk.few rp ;; // B
+
+ .endp
+
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s
new file mode 100644
index 0000000000..0b5816f1be
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s
@@ -0,0 +1,124 @@
+
+// Select C numeric constant
+ .radix C
+ .psr abi64
+ .psr lsb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'SharedStub'
+ .proc SharedStub
+// manual bundling
+ .explicit
+
+ .global PrepareAndDispatch
+// .exclass PrepareAndDispatch, @fullyvisible
+ .type PrepareAndDispatch,@function
+
+SharedStub::
+// 10 arguments, first 8 are the input arguments of previous
+// function call. The 9th one is methodIndex and the 10th is the
+// pointer to the remaining input arguments. The last two arguments
+// are passed in memory.
+ .prologue
+ .save ar.pfs , r41
+// allocate 8 input args, 4 local args, and 5 output args
+ alloc r41 = ar.pfs, 8, 4, 5, 0 // M
+ .save rp, r40
+ mov r40 = rp // I
+ add out4 = 24, sp ;; // I
+
+ .save ar.unat, r42
+ mov r42 = ar.unat // M
+ .fframe 144
+ add sp = -144, sp // A
+// unwind table already knows gp, don't need to specify anything
+ add r43 = 0, gp ;; // A
+
+// We have possible 8 integer registers and 8 float registers that could
+// be arguments. We also have a stack region from the previous
+// stack frame that may hold some stack arguments.
+// We need to write the integer registers to a memory region, write
+// the float registers to a memory region (making sure we don't step
+// on NAT while touching the registers). We also mark the memory
+// address of the stack arguments.
+// We then call PrepareAndDispatch() specifying the three memory
+// region pointers.
+
+
+ .body
+ add out0 = 0, in0 // A move self ptr
+// 144 bytes = 16 byte stack header + 64 byte int space + 64 byte float space
+// methodIndex is at 144 + 16 bytes away from current sp
+// (current frame + previous frame header)
+ ld8 out4 = [out4] // M restarg address
+ add r11 = 160, sp ;; // A address of methodIndex
+
+ ld8 out1 = [r11] // M load methodIndex
+// sp + 16 is the start of intargs
+ add out2 = 16, sp // A address of intargs
+// the intargs take up 64 bytes, so sp + 16 + 64 is the start of floatargs
+ add out3 = 80, sp ;; // A address of floatargs
+
+ add r11 = 0, out2 ;; // A
+ st8.spill [r11] = in1, 8 // M
+ add r10 = 0, out3 ;; // A
+
+ st8.spill [r11] = in2, 8 ;; // M
+ st8.spill [r11] = in3, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in4, 8 ;; // M
+ st8.spill [r11] = in5, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in6, 8 ;; // M
+ st8.spill [r11] = in7 // M
+ fclass.nm p14,p15 = f8,@nat ;; // F
+
+(p14) stfd [r10] = f8, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 = f9,@nat ;; // F
+
+(p12) stfd [r10] = f9, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f10,@nat ;; // F
+
+(p14) stfd [r10] = f10, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f11,@nat ;; // F
+
+(p12) stfd [r10] = f11, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f12,@nat ;; // F
+
+(p14) stfd [r10] = f12, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f13,@nat ;; // F
+
+(p12) stfd [r10] = f13, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f14,@nat ;; // F
+
+(p14) stfd [r10] = f14, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f15,@nat ;; // F
+
+(p12) stfd [r10] = f15, 8 // M
+(p13) add r10 = 8, r10 // A
+
+// branch to PrepareAndDispatch
+ br.call.dptk.few rp = PrepareAndDispatch ;; // B
+
+// epilog
+ mov ar.unat = r42 // M
+ mov ar.pfs = r41 // I
+ mov rp = r40 ;; // I
+
+ add gp = 0, r43 // A
+ add sp = 144, sp // A
+ br.ret.dptk.few rp ;; // B
+
+ .endp
+
+/* Magic indicating no need for an executable stack */
+.section .note.GNU-stack, "", @progbits
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_loongarch64.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_loongarch64.S
new file mode 100644
index 0000000000..ae4e0cf73f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_loongarch64.S
@@ -0,0 +1,52 @@
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ .set NGPRGES, 8
+ .set NFPREGS, 8
+
+ .text
+ .globl SharedStub
+ .hidden SharedStub
+ .type SharedStub,@function
+
+SharedStub:
+ .cfi_startproc
+ move $t0, $sp
+ addi.d $sp, $sp, -8*(NGPRGES+NFPREGS)-16
+ .cfi_def_cfa_offset 8*(NGPRGES+NFPREGS)+16
+ st.d $a0, $sp, 0
+ st.d $a1, $sp, 8
+ st.d $a2, $sp, 16
+ st.d $a3, $sp, 24
+ st.d $a4, $sp, 32
+ st.d $a5, $sp, 40
+ st.d $a6, $sp, 48
+ st.d $a7, $sp, 56
+ fst.d $fa0, $sp, 64
+ fst.d $fa1, $sp, 72
+ fst.d $fa2, $sp, 80
+ fst.d $fa3, $sp, 88
+ fst.d $fa4, $sp, 96
+ fst.d $fa5, $sp, 104
+ fst.d $fa6, $sp, 112
+ fst.d $fa7, $sp, 120
+ st.d $ra, $sp, 136
+ .cfi_offset 1, 136
+
+ /* methodIndex is passed from stub */
+ move $a1, $t6
+ move $a2, $t0
+ move $a3, $sp
+ addi.d $a4, $sp, 8*NGPRGES
+
+ bl PrepareAndDispatch
+
+ ld.d $ra, $sp, 136
+ .cfi_restore 1
+ addi.d $sp, $sp, 8*(NGPRGES+NFPREGS)+16
+ .cfi_def_cfa_offset -8*(NGPRGES+NFPREGS)-16
+ jirl $zero, $ra, 0
+ .cfi_endproc
+
+ .size SharedStub, .-SharedStub
+ .section .note.GNU-stack, "", @progbits
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S
new file mode 100644
index 0000000000..d17301634e
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S
@@ -0,0 +1,116 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* This code is for MIPS using the O32 ABI. */
+
+#ifdef ANDROID
+#include <asm/regdef.h>
+#include <asm/asm.h>
+#include <machine/asm.h>
+#else
+#include <sys/regdef.h>
+#include <sys/asm.h>
+#endif
+
+# NARGSAVE is the argument space in the callers frame, including extra
+# 'shadowed' space for the argument registers. The minimum of 4
+# argument slots is sometimes predefined in the header files.
+#ifndef NARGSAVE
+#define NARGSAVE 4
+#endif
+
+#define LOCALSZ 2 /* gp, ra */
+#define FRAMESZ ((((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK)
+
+#define RAOFF (FRAMESZ - (1*SZREG))
+#define GPOFF (FRAMESZ - (2*SZREG))
+
+#define A0OFF (FRAMESZ + (0*SZREG))
+#define A1OFF (FRAMESZ + (1*SZREG))
+#define A2OFF (FRAMESZ + (2*SZREG))
+#define A3OFF (FRAMESZ + (3*SZREG))
+
+ .text
+
+#define STUB_ENTRY(x) \
+ .if x < 10; \
+ .globl _ZN14nsXPTCStubBase5Stub ##x ##Ev; \
+ .type _ZN14nsXPTCStubBase5Stub ##x ##Ev,@function; \
+ .aent _ZN14nsXPTCStubBase5Stub ##x ##Ev,0; \
+_ZN14nsXPTCStubBase5Stub ##x ##Ev:; \
+ SETUP_GP; \
+ li t0,x; \
+ b sharedstub; \
+ .elseif x < 100; \
+ .globl _ZN14nsXPTCStubBase6Stub ##x ##Ev; \
+ .type _ZN14nsXPTCStubBase6Stub ##x ##Ev,@function; \
+ .aent _ZN14nsXPTCStubBase6Stub ##x ##Ev,0; \
+_ZN14nsXPTCStubBase6Stub ##x ##Ev:; \
+ SETUP_GP; \
+ li t0,x; \
+ b sharedstub; \
+ .elseif x < 1000; \
+ .globl _ZN14nsXPTCStubBase7Stub ##x ##Ev; \
+ .type _ZN14nsXPTCStubBase7Stub ##x ##Ev,@function; \
+ .aent _ZN14nsXPTCStubBase7Stub ##x ##Ev,0; \
+_ZN14nsXPTCStubBase7Stub ##x ##Ev:; \
+ SETUP_GP; \
+ li t0,x; \
+ b sharedstub; \
+ .else; \
+ .err; \
+ .endif
+
+# SENTINEL_ENTRY is handled in the cpp file.
+#define SENTINEL_ENTRY(x)
+
+#
+# open a dummy frame for the function entries
+#
+ .align 2
+ .type dummy,@function
+ .ent dummy, 0
+ .frame sp, FRAMESZ, ra
+dummy:
+ SETUP_GP
+
+#include "xptcstubsdef.inc"
+
+sharedstub:
+ subu sp, FRAMESZ
+
+ # specify the save register mask for gp, ra, a0-a3
+ .mask 0x900000F0, RAOFF-FRAMESZ
+
+ sw ra, RAOFF(sp)
+ SAVE_GP(GPOFF)
+
+ # Micro-optimization: a0 is already loaded, and its slot gets
+ # ignored by PrepareAndDispatch, so no need to save it here.
+ # sw a0, A0OFF(sp)
+ sw a1, A1OFF(sp)
+ sw a2, A2OFF(sp)
+ sw a3, A3OFF(sp)
+
+ la t9, PrepareAndDispatch
+
+ # t0 is methodIndex
+ move a1, t0
+ # have a2 point to the begin of the argument space on stack
+ addiu a2, sp, FRAMESZ
+
+ # PrepareAndDispatch(that, methodIndex, args)
+ jalr t9
+
+ # Micro-optimization: Using jalr explicitly has the side-effect
+ # of not triggering .cprestore. This is ok because we have no
+ # gp reference below this point. It also allows better
+ # instruction sscheduling.
+ # lw gp, GPOFF(fp)
+
+ lw ra, RAOFF(sp)
+ addiu sp, FRAMESZ
+ j ra
+ END(dummy)
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4
new file mode 100644
index 0000000000..33c7b1492c
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4
@@ -0,0 +1,75 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* This code is for MIPS using the O32 ABI. */
+
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+ .text
+ .globl PrepareAndDispatch
+
+NARGSAVE=4 # extra space for the callee to use. gccism
+ # we can put our a0-a3 in our callers space.
+LOCALSZ=2 # gp, ra
+FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+
+define(STUB_NAME, `Stub'$1`__14nsXPTCStubBase')
+
+define(STUB_ENTRY,
+` .globl 'STUB_NAME($1)`
+ .align 2
+ .type 'STUB_NAME($1)`,@function
+ .ent 'STUB_NAME($1)`, 0
+'STUB_NAME($1)`:
+ .frame sp, FRAMESZ, ra
+ .set noreorder
+ .cpload t9
+ .set reorder
+ subu sp, FRAMESZ
+ .cprestore 16
+ li t0, '$1`
+ b sharedstub
+.end 'STUB_NAME($1)`
+
+')
+
+define(SENTINEL_ENTRY, `')
+
+include(xptcstubsdef.inc)
+
+ .globl sharedstub
+ .ent sharedstub
+sharedstub:
+
+ REG_S ra, 20(sp)
+
+ REG_S a0, 24(sp)
+ REG_S a1, 28(sp)
+ REG_S a2, 32(sp)
+ REG_S a3, 36(sp)
+
+ # t0 is methodIndex
+ move a1, t0
+
+ # put the start of a1, a2, a3, and stack
+ move a2, sp
+ addi a2, 24 # have a2 point to sp + 24 (where a0 is)
+
+ # PrepareAndDispatch(that, methodIndex, args)
+ # a0 a1 a2
+ #
+ jal PrepareAndDispatch
+
+ REG_L ra, 20(sp)
+ REG_L a1, 28(sp)
+ REG_L a2, 32(sp)
+
+ addu sp, FRAMESZ
+ j ra
+
+.end sharedstub
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S
new file mode 100644
index 0000000000..11d851536e
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S
@@ -0,0 +1,111 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+LOCALSZ=16
+FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+
+A1OFF=FRAMESZ-(9*SZREG)
+A2OFF=FRAMESZ-(8*SZREG)
+A3OFF=FRAMESZ-(7*SZREG)
+A4OFF=FRAMESZ-(6*SZREG)
+A5OFF=FRAMESZ-(5*SZREG)
+A6OFF=FRAMESZ-(4*SZREG)
+A7OFF=FRAMESZ-(3*SZREG)
+GPOFF=FRAMESZ-(2*SZREG)
+RAOFF=FRAMESZ-(1*SZREG)
+
+F13OFF=FRAMESZ-(16*SZREG)
+F14OFF=FRAMESZ-(15*SZREG)
+F15OFF=FRAMESZ-(14*SZREG)
+F16OFF=FRAMESZ-(13*SZREG)
+F17OFF=FRAMESZ-(12*SZREG)
+F18OFF=FRAMESZ-(11*SZREG)
+F19OFF=FRAMESZ-(10*SZREG)
+
+#define SENTINEL_ENTRY(n) /* defined in cpp file, not here */
+
+#define STUB_ENTRY(x) \
+ .if x < 10; \
+ MAKE_STUB(x, _ZN14nsXPTCStubBase5Stub ##x ##Ev); \
+ .elseif x < 100; \
+ MAKE_STUB(x, _ZN14nsXPTCStubBase6Stub ##x ##Ev); \
+ .elseif x < 1000; \
+ MAKE_STUB(x, _ZN14nsXPTCStubBase7Stub ##x ##Ev); \
+ .else; \
+ .err; \
+ .endif
+
+#define MAKE_STUB(x, name) \
+ .globl name; \
+ .type name,@function; \
+ .aent name,0; \
+name:; \
+ PTR_SUBU sp,FRAMESZ; \
+ SETUP_GP64(GPOFF, name); \
+ li t0,x; \
+ b sharedstub; \
+
+#
+# open a dummy frame for the function entries
+#
+ .text
+ .align 2
+ .type dummy,@function
+ .ent dummy, 0
+dummy:
+ .frame sp, FRAMESZ, ra
+ .mask 0x90000FF0, RAOFF-FRAMESZ
+ .fmask 0x000FF000, F19OFF-FRAMESZ
+
+#include "xptcstubsdef.inc"
+
+sharedstub:
+
+ REG_S a1, A1OFF(sp)
+ REG_S a2, A2OFF(sp)
+ REG_S a3, A3OFF(sp)
+ REG_S a4, A4OFF(sp)
+ REG_S a5, A5OFF(sp)
+ REG_S a6, A6OFF(sp)
+ REG_S a7, A7OFF(sp)
+ REG_S ra, RAOFF(sp)
+
+ s.d $f13, F13OFF(sp)
+ s.d $f14, F14OFF(sp)
+ s.d $f15, F15OFF(sp)
+ s.d $f16, F16OFF(sp)
+ s.d $f17, F17OFF(sp)
+ s.d $f18, F18OFF(sp)
+ s.d $f19, F19OFF(sp)
+
+ # t0 is methodIndex
+ move a1, t0
+
+ # a2 is stack address where extra function params
+ # are stored that do not fit in registers
+ move a2, sp
+ PTR_ADDI a2, FRAMESZ
+
+ # a3 is stack address of a1..a7
+ move a3, sp
+ PTR_ADDI a3, A1OFF
+
+ # a4 is stack address of f13..f19
+ move a4, sp
+ PTR_ADDI a4, F13OFF
+
+ # PrepareAndDispatch(that, methodIndex, args, gprArgs, fpArgs)
+ # a0 a1 a2 a3 a4
+ #
+ jal PrepareAndDispatch
+
+ REG_L ra, RAOFF(sp)
+ RESTORE_GP64
+
+ PTR_ADDU sp, FRAMESZ
+ j ra
+ END(dummy)
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s
new file mode 100644
index 0000000000..9e86848fcf
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s
@@ -0,0 +1,68 @@
+ .LEVEL 1.1
+
+curframesz .EQU 128
+; SharedStub has stack size of 128 bytes
+
+lastframesz .EQU 64
+; the StubN C++ function has a small stack size of 64 bytes
+
+ .SPACE $TEXT$,SORT=8
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
+SharedStub
+ .PROC
+ .CALLINFO CALLER,FRAME=80,SAVE_RP,ARGS_SAVED
+
+ .ENTRY
+ STW %rp,-20(%sp)
+ LDO 128(%sp),%sp
+
+ STW %r19,-32(%r30)
+ STW %r26,-36-curframesz(%r30) ; save arg0 in previous frame
+
+ LDO -80(%r30),%r28
+ FSTD,MA %fr5,8(%r28) ; save darg0
+ FSTD,MA %fr7,8(%r28) ; save darg1
+ FSTW,MA %fr4L,4(%r28) ; save farg0
+ FSTW,MA %fr5L,4(%r28) ; save farg1
+ FSTW,MA %fr6L,4(%r28) ; save farg2
+ FSTW,MA %fr7L,4(%r28) ; save farg3
+
+ ; Former value of register 26 is already properly saved by StubN,
+ ; but register 25-23 are not because of the arguments mismatch
+ STW %r25,-40-curframesz-lastframesz(%r30) ; save r25
+ STW %r24,-44-curframesz-lastframesz(%r30) ; save r24
+ STW %r23,-48-curframesz-lastframesz(%r30) ; save r23
+ COPY %r26,%r25 ; method index is arg1
+ LDW -36-curframesz-lastframesz(%r30),%r26 ; self is arg0
+ LDO -40-curframesz-lastframesz(%r30),%r24 ; normal args is arg2
+ LDO -80(%r30),%r23 ; floating args is arg3
+
+ BL .+8,%r2
+ ADDIL L'PrepareAndDispatch-$PIC_pcrel$0+4,%r2
+ LDO R'PrepareAndDispatch-$PIC_pcrel$1+8(%r1),%r1
+$PIC_pcrel$0
+ LDSID (%r1),%r31
+$PIC_pcrel$1
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+;in=23-26;out=28;
+ BLE 0(%sr0,%r1)
+ COPY %r31,%r2
+
+ LDW -32(%r30),%r19
+
+ LDW -148(%sp),%rp
+ BVE (%rp)
+ .EXIT
+ LDO -128(%sp),%sp
+
+
+ .PROCEND ;in=26;out=28;
+
+ .ALIGN 8
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+ .IMPORT PrepareAndDispatch,CODE
+ .EXPORT SharedStub,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR,LONG_RETURN
+ .END
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s
new file mode 100644
index 0000000000..b45d7763be
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s
@@ -0,0 +1,73 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ .LEVEL 1.1
+ .TEXT
+ .ALIGN 4
+
+curframesz:
+ .EQU 128
+
+
+; SharedStub has stack size of 128 bytes
+
+lastframesz:
+ .EQU 64
+
+; the StubN C++ function has a small stack size of 64 bytes
+
+
+.globl SharedStub
+ .type SharedStub, @function
+
+SharedStub:
+ .PROC
+ .CALLINFO CALLER,FRAME=80,SAVE_RP
+
+ .ENTRY
+ STW %rp,-20(%sp)
+ LDO 128(%sp),%sp
+
+ STW %r19,-32(%r30)
+ STW %r26,-36-curframesz(%r30) ; save arg0 in previous frame
+
+ LDO -80(%r30),%r28
+ FSTD,MA %fr5,8(%r28) ; save darg0
+ FSTD,MA %fr7,8(%r28) ; save darg1
+ FSTW,MA %fr4L,4(%r28) ; save farg0
+ FSTW,MA %fr5L,4(%r28) ; save farg1
+ FSTW,MA %fr6L,4(%r28) ; save farg2
+ FSTW,MA %fr7L,4(%r28) ; save farg3
+
+ ; Former value of register 26 is already properly saved by StubN,
+ ; but register 25-23 are not because of the argument mismatch
+ STW %r25,-40-curframesz-lastframesz(%r30) ; save r25
+ STW %r24,-44-curframesz-lastframesz(%r30) ; save r24
+ STW %r23,-48-curframesz-lastframesz(%r30) ; save r23
+ COPY %r26,%r25 ; method index is arg1
+ LDW -36-curframesz-lastframesz(%r30),%r26 ; self is arg0
+ LDO -40-curframesz-lastframesz(%r30),%r24 ; normal args is arg2
+ LDO -80(%r30),%r23 ; floating args is arg3
+
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR ;in=23-26;out=28;
+ BL PrepareAndDispatch, %r31
+ COPY %r31,%r2
+
+ LDW -32(%r30),%r19
+
+ LDW -148(%sp),%rp
+ LDO -128(%sp),%sp
+
+
+ BV,N (%rp)
+ NOP
+ NOP
+
+ .EXIT
+ .PROCEND ;in=26;out=28;
+
+ .SIZE SharedStub, .-SharedStub
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S
new file mode 100644
index 0000000000..0b884e1fdb
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S
@@ -0,0 +1,112 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+.set r0,0; .set r1,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+#if _CALL_ELF == 2
+#define STACK_PARAMS 96
+#else
+#define STACK_PARAMS 112
+#endif
+
+#if _CALL_ELF == 2
+ .section ".text"
+ .type SharedStub,@function
+ .globl SharedStub
+ # Make the symbol hidden so that the branch from the stub does
+ # not go via a PLT. This is not only better for performance,
+ # but may be necessary to avoid linker errors since there is
+ # no place to restore the TOC register in a sibling call.
+ .hidden SharedStub
+ .align 2
+SharedStub:
+0: addis 2,12,(.TOC.-0b)@ha
+ addi 2,2,(.TOC.-0b)@l
+ .localentry SharedStub,.-SharedStub
+#else
+ .section ".text"
+ .align 2
+ .globl SharedStub
+ # Make the symbol hidden so that the branch from the stub does
+ # not go via a PLT. This is not only better for performance,
+ # but may be necessary to avoid linker errors since there is
+ # no place to restore the TOC register in a sibling call.
+ .hidden SharedStub
+ .section ".opd","aw"
+ .align 3
+
+SharedStub:
+ .quad .SharedStub,.TOC.@tocbase
+ .previous
+ .type SharedStub,@function
+
+.SharedStub:
+#endif
+ mflr r0
+
+ std r4, -56(r1) # Save all GPRS
+ std r5, -48(r1)
+ std r6, -40(r1)
+ std r7, -32(r1)
+ std r8, -24(r1)
+ std r9, -16(r1)
+ std r10, -8(r1)
+
+ stfd f13, -64(r1) # ... and FPRS
+ stfd f12, -72(r1)
+ stfd f11, -80(r1)
+ stfd f10, -88(r1)
+ stfd f9, -96(r1)
+ stfd f8, -104(r1)
+ stfd f7, -112(r1)
+ stfd f6, -120(r1)
+ stfd f5, -128(r1)
+ stfd f4, -136(r1)
+ stfd f3, -144(r1)
+ stfd f2, -152(r1)
+ stfd f1, -160(r1)
+
+ subi r6,r1,56 # r6 --> gprData
+ subi r7,r1,160 # r7 --> fprData
+ addi r5,r1,STACK_PARAMS # r5 --> extra stack args
+
+ std r0, 16(r1)
+
+ stdu r1,-288(r1)
+ # r3 has the 'self' pointer
+ # already
+
+ mr r4,r11 # r4 is methodIndex selector,
+ # passed via r11 in the
+ # nsNSStubBase::StubXX() call
+
+ bl PrepareAndDispatch
+ nop
+
+ ld 1,0(r1) # restore stack
+ ld r0,16(r1) # restore LR
+ mtlr r0
+ blr
+
+#if _CALL_ELF == 2
+ .size SharedStub,.-SharedStub
+#else
+ .size SharedStub,.-.SharedStub
+#endif
+
+ # Magic indicating no need for an executable stack
+ .section .note.GNU-stack, "", @progbits
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4
new file mode 100644
index 0000000000..6dabf334da
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4
@@ -0,0 +1,119 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+# Define the correct name of the stub function based on the object model
+
+define(STUB_NAME,
+ ifelse(AIX_OBJMODEL, ibm,
+ `Stub'$1`__EI14nsXPTCStubBaseFv',
+ `Stub'$1`__14nsXPTCStubBaseFv'))
+
+define(STUB_ENTRY, `
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.'STUB_NAME($1)`{TC},"'STUB_NAME($1)`"
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .'STUB_NAME($1)`
+ .globl 'STUB_NAME($1)`{DS}
+
+.'STUB_NAME($1)`:
+ li r12, '$1`
+ b .SharedStub
+ nop
+
+
+ .toc
+T.18.'STUB_NAME($1)`:
+ .tc H.18.'STUB_NAME($1)`{TC},'STUB_NAME($1)`{DS}
+ .csect 'STUB_NAME($1)`{DS}
+ .long .'STUB_NAME($1)`
+ .long TOC{TC0}
+ .long 0x00000000
+')
+
+define(SENTINEL_ENTRY, `')
+
+include(xptcstubsdef.inc)
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.SharedStub{TC},"SharedStub"
+
+# .text section
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .SharedStub
+ .globl SharedStub{DS}
+ .extern .PrepareAndDispatch
+
+.SharedStub:
+ mflr r0
+ stw r0,8(sp)
+
+ stwu sp,-176(sp) # room for linkage (24), fprData (104), gprData(28)
+ # outgoing params to PrepareAndDispatch (20)
+
+ stw r4,44(sp) # link area (24) + PrepareAndDispatch params (20)
+ stw r5,48(sp)
+ stw r6,52(sp)
+ stw r7,56(sp)
+ stw r8,60(sp)
+ stw r9,64(sp)
+ stw r10,68(sp)
+ stfd f1,72(sp)
+ stfd f2,80(sp)
+ stfd f3,88(sp)
+ stfd f4,96(sp)
+ stfd f5,104(sp)
+ stfd f6,112(sp)
+ stfd f7,120(sp)
+ stfd f8,128(sp)
+ stfd f9,136(sp)
+ stfd f10,144(sp)
+ stfd f11,152(sp)
+ stfd f12,156(sp)
+ stfd f13,164(sp)
+
+ addi r6,sp,44 # gprData
+
+ addi r7,sp,72 # fprData
+ # r3 has the 'self' pointer already
+ mr r4,r12 # methodIndex selector (it is now LATER)
+ addi r5,sp,232 # pointer to callers args area, beyond r3-r10
+ # mapped range
+
+ bl .PrepareAndDispatch
+ nop
+
+
+ lwz r0,184(sp)
+ addi sp,sp,176
+ mtlr r0
+ blr
+
+# .data section
+
+ .toc # 0x00000038
+T.18.SharedStub:
+ .tc H.18.SharedStub{TC},SharedStub{DS}
+
+ .csect SharedStub{DS}
+ .long .SharedStub # "\0\0\0\0"
+ .long TOC{TC0} # "\0\0\0008"
+ .long 0x00000000 # "\0\0\0\0"
+# End csect SharedStub{DS}
+
+# .bss section
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4
new file mode 100644
index 0000000000..24d713cc9b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4
@@ -0,0 +1,97 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+# Define the correct name of the stub function based on the object model
+define(STUB_NAME,
+ ifelse(AIX_OBJMODEL, ibm,
+ `Stub'$1`__EI14nsXPTCStubBaseFv',
+ `Stub'$1`__14nsXPTCStubBaseFv'))
+define(STUB_ENTRY, `
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.'STUB_NAME($1)`{TC},"'STUB_NAME($1)`"
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .'STUB_NAME($1)`
+ .globl 'STUB_NAME($1)`{DS}
+.'STUB_NAME($1)`:
+ li r12, '$1`
+ b .SharedStub
+ nop
+ .toc
+T.18.'STUB_NAME($1)`:
+ .tc H.18.'STUB_NAME($1)`{TC},'STUB_NAME($1)`{DS}
+ .csect 'STUB_NAME($1)`{DS}
+ .llong .'STUB_NAME($1)`
+ .llong TOC{TC0}
+ .llong 0x00000000
+')
+define(SENTINEL_ENTRY, `')
+include(xptcstubsdef.inc)
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.SharedStub{TC},"SharedStub"
+# .text section
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .SharedStub
+ .globl SharedStub{DS}
+ .extern .PrepareAndDispatch
+.SharedStub:
+ mflr r0
+ std r0,16(sp)
+ stdu sp,-248(sp) # room for linkage (24*2), fprData (104), gprData(28*2)
+ # outgoing params to PrepareAndDispatch (40)
+ std r4,88(sp) # link area (48) + PrepareAndDispatch params (20)
+ std r5,96(sp)
+ std r6,104(sp)
+ std r7,112(sp)
+ std r8,120(sp)
+ std r9,128(sp)
+ std r10,136(sp)
+ stfd f1,144(sp)
+ stfd f2,152(sp)
+ stfd f3,160(sp)
+ stfd f4,168(sp)
+ stfd f5,176(sp)
+ stfd f6,184(sp)
+ stfd f7,192(sp)
+ stfd f8,200(sp)
+ stfd f9,208(sp)
+ stfd f10,216(sp)
+ stfd f11,224(sp)
+ stfd f12,232(sp)
+ stfd f13,240(sp)
+ addi r6,sp,88 # gprData
+ addi r7,sp,144 # fprData
+ # r3 has the 'self' pointer already
+ mr r4,r12 # methodIndex selector (it is now LATER)
+ addi r5,sp,360 # pointer to callers args area, beyond r3-r10
+ # mapped range
+ bl .PrepareAndDispatch
+ nop
+ ld r0,264(sp)
+ addi sp,sp,248
+ mtlr r0
+ blr
+# .data section
+ .toc # 0x00000038
+T.18.SharedStub:
+ .tc H.18.SharedStub{TC},SharedStub{DS}
+ .csect SharedStub{DS}
+ .llong .SharedStub # "\0\0\0\0"
+ .llong TOC{TC0} # "\0\0\0008"
+ .llong 0x00000000 # "\0\0\0\0"
+# End csect SharedStub{DS}
+# .bss section
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4
new file mode 100644
index 0000000000..dda5378503
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4
@@ -0,0 +1,114 @@
+/* -*- Mode: asm -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ .text
+ .globl _SharedStub
+dnl
+define(STUB_MANGLED_ENTRY,
+` .globl '$2`
+ .align 2
+'$2`:
+ addi r12, 0,'$1`
+ b _SharedStub')
+dnl
+define(STUB_ENTRY,
+` .if '$1` < 10
+STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase5Stub'$1`Ev')
+ .elseif '$1` < 100
+STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase6Stub'$1`Ev')
+ .elseif '$1` < 1000
+STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase7Stub'$1`Ev')
+ .else
+ .err "Stub'$1` >= 1000 not yet supported."
+ .endif
+')
+dnl
+define(SENTINEL_ENTRY, `')
+dnl
+include(xptcstubsdef.inc)
+dnl
+// See also xptcstubs_ppc_rhapsody.cpp:PrepareAndDispatch.
+_SharedStub:
+ // Prolog(ue)
+ mflr r0 // Save the link register in the caller's
+ stw r0, 8(r1) // stack frame
+ stwu r1,-176(r1) // Allocate stack space for our own frame and
+ // adjust stack pointer
+
+ // Linkage area, 0(r1) to 24(r1)
+ // Original sp saved at 0(r1)
+
+ // Parameter area, 20 bytes from 24(r1) to
+ // 44(r1) to accomodate 5 arguments passed
+ // to PrepareAndDispatch
+
+ // Local variables, 132 bytes from 44(r1)
+ // to 176(r1), to accomodate 5 words and
+ // 13 doubles
+
+ stw r4, 44(r1) // Save parameters passed in GPRs r4-r10;
+ stw r5, 48(r1) // a pointer to here will be passed to
+ stw r6, 52(r1) // PrepareAndDispatch for access to
+ stw r7, 56(r1) // arguments passed in registers. r3,
+ stw r8, 60(r1) // the self pointer, is used for the
+ stw r9, 64(r1) // call but isn't otherwise needed in
+ stw r10, 68(r1) // PrepareAndDispatch, so it is not saved.
+
+ stfd f1, 72(r1) // Do the same for floating-point parameters
+ stfd f2, 80(r1) // passed in FPRs f1-f13
+ stfd f3, 88(r1)
+ stfd f4, 96(r1)
+ stfd f5, 104(r1)
+ stfd f6, 112(r1)
+ stfd f7, 120(r1)
+ stfd f8, 128(r1)
+ stfd f9, 136(r1)
+ stfd f10, 144(r1)
+ stfd f11, 152(r1)
+ stfd f12, 160(r1)
+ stfd f13, 168(r1)
+
+ // Set up parameters for call to
+ // PrepareAndDispatch. argument=
+ // 0, pointer to self, already in r3
+ mr r4,r12 // 1, stub number
+ addi r5, r1, 204 // 2, pointer to the parameter area in our
+ // caller's stack, for access to
+ // parameters beyond those passed in
+ // registers. Skip past the first parameter
+ // (corresponding to r3) for the same reason
+ // as above. 176 (size of our frame) + 24
+ // (size of caller's linkage) + 4 (skipped
+ // parameter)
+ addi r6, r1, 44 // 3, pointer to saved GPRs
+ addi r7, r1, 72 // 4, pointer to saved FPRs
+
+ bl L_PrepareAndDispatch$stub
+ // Do it
+ nop // Leave room for linker magic
+
+ // Epilog(ue)
+ lwz r0, 184(r1) // Retrieve old link register value
+ addi r1, r1, 176 // Restore stack pointer
+ mtlr r0 // Restore link register
+ blr // Return
+
+.picsymbol_stub
+L_PrepareAndDispatch$stub: // Standard PIC symbol stub
+ .indirect_symbol _PrepareAndDispatch
+ mflr r0
+ bcl 20,31,L1$pb
+L1$pb:
+ mflr r11
+ addis r11,r11,ha16(L1$lz-L1$pb)
+ mtlr r0
+ lwz r12,lo16(L1$lz-L1$pb)(r11)
+ mtctr r12
+ addi r11,r11,lo16(L1$lz-L1$pb)
+ bctr
+.lazy_symbol_pointer
+L1$lz:
+ .indirect_symbol _PrepareAndDispatch
+ .long dyld_stub_binding_helper
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S
new file mode 100644
index 0000000000..e383468865
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S
@@ -0,0 +1,77 @@
+// -*- Mode: Asm -*-
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl SharedStub
+ .type SharedStub,@function
+
+SharedStub:
+ stwu sp,-112(sp) // room for
+ // linkage (8),
+ // gprData (32),
+ // fprData (64),
+ // stack alignment(8)
+ mflr r0
+ stw r0,116(sp) // save LR backchain
+
+ stw r4,12(sp) // save GP registers
+ stw r5,16(sp) // (n.b. that we don't save r3
+ stw r6,20(sp) // because PrepareAndDispatch() is savvy)
+ stw r7,24(sp)
+ stw r8,28(sp)
+ stw r9,32(sp)
+ stw r10,36(sp)
+#ifndef __NO_FPRS__
+ stfd f1,40(sp) // save FP registers
+ stfd f2,48(sp)
+ stfd f3,56(sp)
+ stfd f4,64(sp)
+ stfd f5,72(sp)
+ stfd f6,80(sp)
+ stfd f7,88(sp)
+ stfd f8,96(sp)
+#endif
+
+ // r3 has the 'self' pointer already
+
+ mr r4,r11 // r4 <= methodIndex selector, passed
+ // via r11 in the nsXPTCStubBase::StubXX() call
+
+ addi r5,sp,120 // r5 <= pointer to callers args area,
+ // beyond r3-r10/f1-f8 mapped range
+
+ addi r6,sp,8 // r6 <= gprData
+#ifndef __NO_FPRS__
+ addi r7,sp,40 // r7 <= fprData
+#else
+ li r7, 0 // r7 should be unused
+#endif
+
+ bl PrepareAndDispatch@local // Go!
+
+ lwz r0,116(sp) // restore LR
+ mtlr r0
+ la sp,112(sp) // clean up the stack
+ blr
+
+ /* Magic indicating no need for an executable stack */
+ .section .note.GNU-stack, "", @progbits
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S
new file mode 100644
index 0000000000..968ad428f8
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S
@@ -0,0 +1,72 @@
+// -*- Mode: Asm -*-
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl SharedStub
+ .type SharedStub,@function
+
+SharedStub:
+ stwu sp,-112(sp) // room for
+ // linkage (8),
+ // gprData (32),
+ // fprData (64),
+ // stack alignment(8)
+ mflr r0
+ stw r0,116(sp) // save LR backchain
+
+ stw r4,12(sp) // save GP registers
+ stw r5,16(sp) // (n.b. that we don't save r3
+ stw r6,20(sp) // because PrepareAndDispatch() is savvy)
+ stw r7,24(sp)
+ stw r8,28(sp)
+ stw r9,32(sp)
+ stw r10,36(sp)
+
+ stfd f1,40(sp) // save FP registers
+ stfd f2,48(sp)
+ stfd f3,56(sp)
+ stfd f4,64(sp)
+ stfd f5,72(sp)
+ stfd f6,80(sp)
+ stfd f7,88(sp)
+ stfd f8,96(sp)
+
+ // r3 has the 'self' pointer already
+
+ mr r4,r11 // r4 <= methodIndex selector, passed
+ // via r11 in the nsXPTCStubBase::StubXX() call
+
+ addi r5,sp,120 // r5 <= pointer to callers args area,
+ // beyond r3-r10/f1-f8 mapped range
+
+ addi r6,sp,8 // r6 <= gprData
+ addi r7,sp,40 // r7 <= fprData
+
+ bl PrepareAndDispatch@local // Go!
+
+ lwz r0,116(sp) // restore LR
+ mtlr r0
+ la sp,112(sp) // clean up the stack
+ blr
+
+ // Magic indicating no need for an executable stack
+ .section .note.GNU-stack, "", @progbits
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_riscv64.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_riscv64.S
new file mode 100644
index 0000000000..02bb812d59
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_riscv64.S
@@ -0,0 +1,53 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ .set NGPREGS, 8
+ .set NFPREGS, 8
+
+ .text
+ .globl SharedStub
+ .hidden SharedStub
+ .type SharedStub,@function
+
+SharedStub:
+ .cfi_startproc
+ mv t1, sp
+ addi sp, sp, -8*(NGPREGS+NFPREGS)-16
+ .cfi_adjust_cfa_offset 8*(NGPREGS+NFPREGS)+16
+ sd a0, 0(sp)
+ sd a1, 8(sp)
+ sd a2, 16(sp)
+ sd a3, 24(sp)
+ sd a4, 32(sp)
+ sd a5, 40(sp)
+ sd a6, 48(sp)
+ sd a7, 56(sp)
+ fsd fa0, 64(sp)
+ fsd fa1, 72(sp)
+ fsd fa2, 80(sp)
+ fsd fa3, 88(sp)
+ fsd fa4, 96(sp)
+ fsd fa5, 104(sp)
+ fsd fa6, 112(sp)
+ fsd fa7, 120(sp)
+ sd ra, 136(sp)
+ .cfi_rel_offset ra, 136
+
+ /* methodIndex is passed from stub */
+ mv a1, t0
+ mv a2, t1
+ mv a3, sp
+ addi a4, sp, 8*NGPREGS
+
+ call PrepareAndDispatch
+
+ ld ra, 136(sp)
+ .cfi_restore ra
+ addi sp, sp, 8*(NGPREGS+NFPREGS)+16
+ .cfi_adjust_cfa_offset -8*(NGPREGS+NFPREGS)-16
+ ret
+ .cfi_endproc
+
+ .size SharedStub, . - SharedStub
+ .section .note.GNU-stack, "", @progbits
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s
new file mode 100644
index 0000000000..ab97a890c3
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s
@@ -0,0 +1,50 @@
+/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 0x7ff + 136, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ stx %i1, [%fp + 0x7ff + 136]
+ stx %i2, [%fp + 0x7ff + 144]
+ stx %i3, [%fp + 0x7ff + 152]
+ stx %i4, [%fp + 0x7ff + 160]
+ stx %i5, [%fp + 0x7ff + 168]
+! now we can build our own stack frame
+ save %sp,-(128 + 64),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 64
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s
new file mode 100644
index 0000000000..9b448d7c7d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s
@@ -0,0 +1,49 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ st %i1, [%fp + 72]
+ st %i2, [%fp + 76]
+ st %i3, [%fp + 80]
+ st %i4, [%fp + 84]
+ st %i5, [%fp + 88]
+! now we can build our own stack frame
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s
new file mode 100644
index 0000000000..871556d4c6
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s
@@ -0,0 +1,49 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ st %i1, [%fp + 72]
+ st %i2, [%fp + 76]
+ st %i3, [%fp + 80]
+ st %i4, [%fp + 84]
+ st %i5, [%fp + 88]
+! now we can build our own stack frame
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s
new file mode 100644
index 0000000000..9b448d7c7d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s
@@ -0,0 +1,49 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ st %i1, [%fp + 72]
+ st %i2, [%fp + 76]
+ st %i3, [%fp + 80]
+ st %i4, [%fp + 84]
+ st %i5, [%fp + 88]
+! now we can build our own stack frame
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp
new file mode 100644
index 0000000000..3d1addedaf
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp
@@ -0,0 +1,18 @@
+/* -*- Mode: C -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if defined(__i386__)
+#include "xptcstubs_gcc_x86_unix.cpp"
+#elif defined(__x86_64__)
+#include "xptcstubs_x86_64_darwin.cpp"
+#elif defined(__ppc__)
+#include "xptcstubs_ppc_rhapsody.cpp"
+#elif defined(__arm__)
+#include "xptcstubs_arm.cpp"
+#elif defined(__aarch64__)
+#include "xptcstubs_aarch64.cpp"
+#else
+#error unknown cpu architecture
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp
new file mode 100644
index 0000000000..5f0c3ba04e
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp
@@ -0,0 +1,132 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptc_gcc_x86_unix.h"
+
+extern "C" {
+static nsresult ATTRIBUTE_USED
+__attribute__ ((regparm (3)))
+PrepareAndDispatch(uint32_t methodIndex, nsXPTCStubBase* self, uint32_t* args)
+{
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext)
+ ap++;
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ dp->val.p = (void*) *ap;
+ switch(type)
+ {
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ default : break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+} // extern "C"
+
+#if !defined(XP_MACOSX)
+
+#define STUB_HEADER(a, b) ".hidden " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev,@function\n"
+
+#define STUB_SIZE(a, b) ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev\n\t"
+
+#else
+
+#define STUB_HEADER(a, b)
+#define STUB_SIZE(a, b)
+
+#endif
+
+// gcc3 mangling tends to insert the length of the method name
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 2\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ STUB_HEADER(5, n) \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ STUB_HEADER(6, n) \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ STUB_HEADER(7, n) \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp " SYMBOL_UNDERSCORE "SharedStub\n\t" \
+ ".if " #n " < 10\n\t" \
+ STUB_SIZE(5, n) \
+ ".elseif " #n " < 100\n\t" \
+ STUB_SIZE(6, n) \
+ ".else\n\t" \
+ STUB_SIZE(7, n) \
+ ".endif");
+
+// static nsresult SharedStub(uint32_t methodIndex) __attribute__((regparm(1)))
+asm(".text\n\t"
+ ".align 2\n\t"
+#if !defined(XP_MACOSX)
+ ".type " SYMBOL_UNDERSCORE "SharedStub,@function\n\t"
+#endif
+ SYMBOL_UNDERSCORE "SharedStub:\n\t"
+ "leal 0x08(%esp), %ecx\n\t"
+ "movl 0x04(%esp), %edx\n\t"
+ "jmp " SYMBOL_UNDERSCORE "PrepareAndDispatch\n\t"
+#if !defined(XP_MACOSX)
+ ".size " SYMBOL_UNDERSCORE "SharedStub,.-" SYMBOL_UNDERSCORE "SharedStub"
+#endif
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+void
+xptc_dummy()
+{
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp
new file mode 100644
index 0000000000..4bee192886
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp
@@ -0,0 +1,139 @@
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+
+#include "xptcprivate.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+// "This code is for IA64 only"
+
+/* Implement shared vtbl methods. */
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint64_t* intargs, uint64_t* floatargs, uint64_t* restargs)
+{
+
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint64_t* iargs = intargs;
+ uint64_t* fargs = floatargs;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ for(i = 0; i < paramCount; ++i)
+ {
+ int isfloat = 0;
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ MOZ_CRASH("NYI: support implicit JSContext*, bug 1475699");
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ dp->val.p = (void*) *iargs;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) iargs;
+ dp->val.p = (void*) (*(adr+1));
+#endif
+ }
+ else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *(iargs); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(iargs); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *(iargs); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *(iargs); break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(iargs); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(iargs); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *(iargs); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *(iargs); break;
+ case nsXPTType::T_FLOAT :
+ isfloat = 1;
+ if (i < 7)
+ dp->val.f = (float) *((double*) fargs); /* register */
+ else
+ dp->val.u32 = *(fargs); /* memory */
+ break;
+ case nsXPTType::T_DOUBLE :
+ isfloat = 1;
+ dp->val.u64 = *(fargs);
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = *(iargs); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(iargs); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *(iargs); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ if (i < 7)
+ {
+ /* we are parsing register arguments */
+ if (i == 6)
+ {
+ // run out of register arguments, move on to memory arguments
+ iargs = restargs;
+ fargs = restargs;
+ }
+ else
+ {
+ ++iargs; // advance one integer register slot
+ if (isfloat) ++fargs; // advance float register slot if isfloat
+ }
+ }
+ else
+ {
+ /* we are parsing memory arguments */
+ ++iargs;
+ ++fargs;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t) methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(uint64_t,uint64_t,uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t *);
+
+/* Variable a0-a7 were put there so we can have access to the 8 input
+ registers on Stubxyz entry */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n(uint64_t a1, \
+uint64_t a2,uint64_t a3,uint64_t a4,uint64_t a5,uint64_t a6,uint64_t a7, \
+uint64_t a8) \
+{ uint64_t a0 = (uint64_t) this; \
+ return SharedStub(a0,a1,a2,a3,a4,a5,a6,a7,(uint64_t) n, &a8); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp
new file mode 100644
index 0000000000..cc74e4db57
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp
@@ -0,0 +1,142 @@
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+
+#include "xptcprivate.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+// "This code is for IA64 only"
+
+/* Implement shared vtbl methods. */
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint64_t* intargs, uint64_t* floatargs, uint64_t* restargs)
+{
+
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint64_t* iargs = intargs;
+ uint64_t* fargs = floatargs;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (! info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ for(i = 0; i < paramCount; ++i)
+ {
+ int isfloat = 0;
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ MOZ_CRASH("NYI: support implicit JSContext*, bug 1475699");
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ dp->val.p = (void*) *iargs;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) iargs;
+ dp->val.p = (void*) (*(adr+1));
+#endif
+ }
+ else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *(iargs); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(iargs); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *(iargs); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *(iargs); break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(iargs); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(iargs); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *(iargs); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *(iargs); break;
+ case nsXPTType::T_FLOAT :
+ isfloat = 1;
+ if (i < 7)
+ dp->val.f = (float) *((double*) fargs); /* register */
+ else
+ dp->val.u32 = *(fargs); /* memory */
+ break;
+ case nsXPTType::T_DOUBLE :
+ isfloat = 1;
+ dp->val.u64 = *(fargs);
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = *(iargs); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(iargs); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *(iargs); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ if (i < 7)
+ {
+ /* we are parsing register arguments */
+ if (i == 6)
+ {
+ // run out of register arguments, move on to memory arguments
+ iargs = restargs;
+ fargs = restargs;
+ }
+ else
+ {
+ ++iargs; // advance one integer register slot
+ if (isfloat) ++fargs; // advance float register slot if isfloat
+ }
+ }
+ else
+ {
+ /* we are parsing memory arguments */
+ ++iargs;
+ ++fargs;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t) methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(uint64_t,uint64_t,uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t *);
+
+/* Variable a0-a7 were put there so we can have access to the 8 input
+ registers on Stubxyz entry */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n(uint64_t a1, \
+uint64_t a2,uint64_t a3,uint64_t a4,uint64_t a5,uint64_t a6,uint64_t a7, \
+uint64_t a8) \
+{ uint64_t a0 = (uint64_t) this; \
+ return SharedStub(a0,a1,a2,a3,a4,a5,a6,a7,(uint64_t) n, &a8); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp
new file mode 100644
index 0000000000..74ffa0c539
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp
@@ -0,0 +1,179 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+/* Prototype specifies unmangled function name and disables unused warning */
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args)
+__asm__("PrepareAndDispatch") ATTRIBUTE_USED;
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args)
+{
+ const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ // args[0] to args[NUM_ARG_REGS] hold floating point register values
+ uint64_t* ap = args + NUM_ARG_REGS;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext)
+ ap++;
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = (int8_t) *ap; break;
+ case nsXPTType::T_I16 : dp->val.i16 = (int16_t) *ap; break;
+ case nsXPTType::T_I32 : dp->val.i32 = (int32_t) *ap; break;
+ case nsXPTType::T_I64 : dp->val.i64 = (int64_t) *ap; break;
+ case nsXPTType::T_U8 : dp->val.u8 = (uint8_t) *ap; break;
+ case nsXPTType::T_U16 : dp->val.u16 = (uint16_t) *ap; break;
+ case nsXPTType::T_U32 : dp->val.u32 = (uint32_t) *ap; break;
+ case nsXPTType::T_U64 : dp->val.u64 = (uint64_t) *ap; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // floats passed via registers are stored as doubles
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (uint64_t) args[i];
+ dp->val.f = (float) dp->val.d; // convert double to float
+ }
+ else
+ dp->val.u32 = (uint32_t) *ap;
+ break;
+ case nsXPTType::T_DOUBLE :
+ // doubles passed via registers are also stored
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap;
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = (bool) *ap; break;
+ case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break;
+ case nsXPTType::T_WCHAR : dp->val.wc = (char16_t) *ap; break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+/*
+ * SharedStub()
+ * Collects arguments and calls PrepareAndDispatch. The "methodIndex" is
+ * passed to this function via $1 to preserve the argument registers.
+ */
+__asm__(
+ "#### SharedStub ####\n"
+".text\n\t"
+ ".align 5\n\t"
+ ".ent SharedStub\n"
+"SharedStub:\n\t"
+ ".frame $30,96,$26,0\n\t"
+ ".mask 0x4000000,-96\n\t"
+ "ldgp $29,0($27)\n"
+"$SharedStub..ng:\n\t"
+ "subq $30,96,$30\n\t"
+ "stq $26,0($30)\n\t"
+ ".prologue 1\n\t"
+
+ /*
+ * Store arguments passed via registers to the stack.
+ * Floating point registers are stored as doubles and converted
+ * to floats in PrepareAndDispatch if necessary.
+ */
+ "stt $f17,16($30)\n\t" /* floating point registers */
+ "stt $f18,24($30)\n\t"
+ "stt $f19,32($30)\n\t"
+ "stt $f20,40($30)\n\t"
+ "stt $f21,48($30)\n\t"
+ "stq $17,56($30)\n\t" /* integer registers */
+ "stq $18,64($30)\n\t"
+ "stq $19,72($30)\n\t"
+ "stq $20,80($30)\n\t"
+ "stq $21,88($30)\n\t"
+
+ /*
+ * Call PrepareAndDispatch function.
+ */
+ "bis $1,$1,$17\n\t" /* pass "methodIndex" */
+ "addq $30,16,$18\n\t" /* pass "args" */
+ "bsr $26,$PrepareAndDispatch..ng\n\t"
+
+ "ldq $26,0($30)\n\t"
+ "addq $30,96,$30\n\t"
+ "ret $31,($26),1\n\t"
+ ".end SharedStub"
+ );
+
+/*
+ * nsresult nsXPTCStubBase::Stub##n()
+ * Sets register $1 to "methodIndex" and jumps to SharedStub.
+ */
+#define STUB_MANGLED_ENTRY(n, symbol) \
+ "#### Stub"#n" ####" "\n\t" \
+ ".text" "\n\t" \
+ ".align 5" "\n\t" \
+ ".globl " symbol "\n\t" \
+ ".ent " symbol "\n" \
+symbol ":" "\n\t" \
+ ".frame $30,0,$26,0" "\n\t" \
+ "ldgp $29,0($27)" "\n" \
+"$" symbol "..ng:" "\n\t" \
+ ".prologue 1" "\n\t" \
+ "lda $1,"#n "\n\t" \
+ "br $31,$SharedStub..ng" "\n\t" \
+ ".end " symbol
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".if "#n" < 10" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase5Stub"#n"Ev") "\n\t" \
+ ".elseif "#n" < 100" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase6Stub"#n"Ev") "\n\t" \
+ ".elseif "#n" < 1000" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase7Stub"#n"Ev") "\n\t" \
+ ".else" "\n\t" \
+ ".err \"Stub"#n" >= 1000 not yet supported.\"" "\n\t" \
+ ".endif" \
+ );
+
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp
new file mode 100644
index 0000000000..15665de872
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp
@@ -0,0 +1,178 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+static nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint32_t* a_gpr, uint64_t *a_fpr, uint32_t *a_ov)
+{
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no info");
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint32_t gpr = 1, fpr = 0;
+
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (gpr < 5)
+ a_gpr++, gpr++;
+ else
+ a_ov++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (gpr < 5)
+ dp->val.p = (void*) *a_gpr++, gpr++;
+ else
+ dp->val.p = (void*) *a_ov++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ dp->val.i8 = *((int32_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i8 = *((int32_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ dp->val.i16 = *((int32_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i16 = *((int32_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ dp->val.i32 = *((int32_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i32 = *((int32_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 4)
+ dp->val.i64 = *((int64_t*) a_gpr), a_gpr+=2, gpr+=2;
+ else
+ dp->val.i64 = *((int64_t*) a_ov ), a_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ dp->val.u8 = *((uint32_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u8 = *((uint32_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ dp->val.u16 = *((uint32_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u16 = *((uint32_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ dp->val.u32 = *((uint32_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u32 = *((uint32_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 4)
+ dp->val.u64 = *((uint64_t*)a_gpr), a_gpr+=2, gpr+=2;
+ else
+ dp->val.u64 = *((uint64_t*)a_ov ), a_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 2)
+ dp->val.f = *((float*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.f = *((float*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 2)
+ dp->val.d = *((double*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.d = *((double*) a_ov ), a_ov+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ dp->val.b = *((uint32_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.b = *((uint32_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ dp->val.c = *((uint32_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.c = *((uint32_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ dp->val.wc = *((uint32_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.wc = *((uint32_t*)a_ov ), a_ov++;
+ break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ uint32_t a_gpr[4]; \
+ uint64_t a_fpr[2]; \
+ uint32_t *a_ov; \
+ \
+ __asm__ __volatile__ \
+ ( \
+ "l %0,0(15)\n\t" \
+ "ahi %0,96\n\t" \
+ "stm 3,6,0(%3)\n\t" \
+ "std 0,%1\n\t" \
+ "std 2,%2\n\t" \
+ : "=&a" (a_ov), \
+ "=m" (a_fpr[0]), \
+ "=m" (a_fpr[1]) \
+ : "a" (a_gpr) \
+ : "memory", "cc", \
+ "3", "4", "5", "6" \
+ ); \
+ \
+ return PrepareAndDispatch(this, n, a_gpr, a_fpr, a_ov); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp
new file mode 100644
index 0000000000..75ecd83795
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp
@@ -0,0 +1,182 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+static nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint64_t* a_gpr, uint64_t *a_fpr, uint64_t *a_ov)
+{
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no info");
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint32_t gpr = 1, fpr = 0;
+
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (gpr < 5)
+ a_gpr++, gpr++;
+ else
+ a_ov++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (gpr < 5)
+ dp->val.p = (void*) *a_gpr++, gpr++;
+ else
+ dp->val.p = (void*) *a_ov++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ dp->val.i8 = *((int64_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i8 = *((int64_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ dp->val.i16 = *((int64_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i16 = *((int64_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ dp->val.i32 = *((int64_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i32 = *((int64_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 5)
+ dp->val.i64 = *((int64_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i64 = *((int64_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ dp->val.u8 = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u8 = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ dp->val.u16 = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u16 = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ dp->val.u32 = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u32 = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 5)
+ dp->val.u64 = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u64 = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 4)
+ dp->val.f = *((float*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.f = *(((float*) a_ov )+1), a_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 4)
+ dp->val.d = *((double*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.d = *((double*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ dp->val.b = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.b = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ dp->val.c = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.c = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ dp->val.wc = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.wc = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ uint64_t a_gpr[4]; \
+ uint64_t a_fpr[4]; \
+ uint64_t *a_ov; \
+ \
+ __asm__ __volatile__ \
+ ( \
+ "lg %0,0(15)\n\t" \
+ "aghi %0,160\n\t" \
+ "stmg 3,6,0(%5)\n\t"\
+ "std 0,%1\n\t" \
+ "std 2,%2\n\t" \
+ "std 4,%3\n\t" \
+ "std 6,%4\n\t" \
+ : "=&a" (a_ov), \
+ "=m" (a_fpr[0]), \
+ "=m" (a_fpr[1]), \
+ "=m" (a_fpr[2]), \
+ "=m" (a_fpr[3]) \
+ : "a" (a_gpr) \
+ : "memory", "cc", \
+ "3", "4", "5", "6" \
+ ); \
+ \
+ return PrepareAndDispatch(this, n, a_gpr, a_fpr, a_ov); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_loongarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_loongarch64.cpp
new file mode 100644
index 0000000000..02ba47d134
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_loongarch64.cpp
@@ -0,0 +1,159 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, V. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xptcprivate.h"
+
+extern "C" nsresult ATTRIBUTE_USED PrepareAndDispatch(nsXPTCStubBase* self,
+ uint32_t methodIndex,
+ uint64_t* args,
+ uint64_t* gpregs,
+ double* fpregs) {
+ static const uint32_t GPR_COUNT = 8;
+ static const uint32_t FPR_COUNT = 8;
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+
+ uint32_t paramCount = info->GetParamCount();
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint64_t* ap = args;
+ uint32_t nr_gpr = 1; // skip the arg which is 'self'
+ uint32_t nr_fpr = 0;
+ uint64_t value;
+
+ for (uint32_t i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (nr_gpr < GPR_COUNT)
+ nr_gpr++;
+ else
+ ap++;
+ }
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT) {
+ dp->val.d = fpregs[nr_fpr++];
+ } else if (nr_gpr < GPR_COUNT) {
+ memcpy(&dp->val.d, &gpregs[nr_gpr++], sizeof(dp->val.d));
+ } else {
+ memcpy(&dp->val.d, ap++, sizeof(dp->val.d));
+ }
+ continue;
+ }
+
+ if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT) {
+ memcpy(&dp->val.f, &fpregs[nr_fpr++], sizeof(dp->val.f));
+ } else if (nr_gpr < GPR_COUNT) {
+ memcpy(&dp->val.f, &gpregs[nr_gpr++], sizeof(dp->val.f));
+ } else {
+ memcpy(&dp->val.f, ap++, sizeof(dp->val.f));
+ }
+ continue;
+ }
+
+ if (nr_gpr < GPR_COUNT) {
+ value = gpregs[nr_gpr++];
+ } else {
+ value = *ap++;
+ }
+
+ if (param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*)value;
+ continue;
+ }
+
+ switch (type) {
+ case nsXPTType::T_I8:
+ dp->val.i8 = (int8_t)value;
+ break;
+ case nsXPTType::T_I16:
+ dp->val.i16 = (int16_t)value;
+ break;
+ case nsXPTType::T_I32:
+ dp->val.i32 = (int32_t)value;
+ break;
+ case nsXPTType::T_I64:
+ dp->val.i64 = (int64_t)value;
+ break;
+ case nsXPTType::T_U8:
+ dp->val.u8 = (uint8_t)value;
+ break;
+ case nsXPTType::T_U16:
+ dp->val.u16 = (uint16_t)value;
+ break;
+ case nsXPTType::T_U32:
+ dp->val.u32 = (uint32_t)value;
+ break;
+ case nsXPTType::T_U64:
+ dp->val.u64 = (uint64_t)value;
+ break;
+ case nsXPTType::T_BOOL:
+ dp->val.b = (bool)(uint8_t)value;
+ break;
+ case nsXPTType::T_CHAR:
+ dp->val.c = (char)value;
+ break;
+ case nsXPTType::T_WCHAR:
+ dp->val.wc = (wchar_t)value;
+ break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+ return result;
+}
+
+// Load $t6 with the constant 'n' and branch to SharedStub().
+// clang-format off
+#define STUB_ENTRY(n) \
+ __asm__( \
+ ".text\n\t" \
+ ".if "#n" < 10 \n\t" \
+ ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ ".hidden _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \
+ "_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
+ ".elseif "#n" < 100 \n\t" \
+ ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ ".hidden _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
+ "_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ ".elseif "#n" < 1000 \n\t" \
+ ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ ".hidden _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \
+ "_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
+ ".else \n\t" \
+ ".err \"stub number "#n" >= 1000 not yet supported\"\n" \
+ ".endif \n\t" \
+ "li.d $t6, "#n" \n\t" \
+ "b SharedStub \n" \
+ ".if "#n" < 10 \n\t" \
+ ".size _ZN14nsXPTCStubBase5Stub"#n"Ev,.-_ZN14nsXPTCStubBase5Stub"#n"Ev\n\t" \
+ ".elseif "#n" < 100 \n\t" \
+ ".size _ZN14nsXPTCStubBase6Stub"#n"Ev,.-_ZN14nsXPTCStubBase6Stub"#n"Ev\n\t" \
+ ".else \n\t" \
+ ".size _ZN14nsXPTCStubBase7Stub"#n"Ev,.-_ZN14nsXPTCStubBase7Stub"#n"Ev\n\t" \
+ ".endif" \
+);
+// clang-format on
+
+#define SENTINEL_ENTRY(n) \
+ nsresult nsXPTCStubBase::Sentinel##n() { \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+ }
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp
new file mode 100644
index 0000000000..7e686b2b08
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xptcprivate.h"
+
+#include <stdint.h>
+
+/*
+ * This is for MIPS O32 ABI
+ * Args contains a0-3 and then the stack.
+ * Because a0 is 'this', we want to skip it
+ */
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+ args++; // always skip over a0
+
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext)
+ ap++;
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+
+ switch(type)
+ {
+ case nsXPTType::T_I64 :
+ if ((intptr_t)ap & 4) ap++;
+ dp->val.i64 = *((int64_t*) ap); ap++;
+ break;
+ case nsXPTType::T_U64 :
+ if ((intptr_t)ap & 4) ap++;
+ dp->val.u64 = *((int64_t*) ap); ap++;
+ break;
+ case nsXPTType::T_DOUBLE:
+ if ((intptr_t)ap & 4) ap++;
+ dp->val.d = *((double*) ap); ap++;
+ break;
+#ifdef IS_LITTLE_ENDIAN
+ default:
+ dp->val.p = (void*) *ap;
+ break;
+#else
+ case nsXPTType::T_I8 : dp->val.i8 = (int8_t) *ap; break;
+ case nsXPTType::T_I16 : dp->val.i16 = (int16_t) *ap; break;
+ case nsXPTType::T_I32 : dp->val.i32 = (int32_t) *ap; break;
+ case nsXPTType::T_U8 : dp->val.u8 = (uint8_t) *ap; break;
+ case nsXPTType::T_U16 : dp->val.u16 = (uint16_t) *ap; break;
+ case nsXPTType::T_U32 : dp->val.u32 = (uint32_t) *ap; break;
+ case nsXPTType::T_BOOL : dp->val.b = (bool) *ap; break;
+ case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break;
+ case nsXPTType::T_WCHAR : dp->val.wc = (wchar_t) *ap; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *(float *) ap; break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+#endif
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+#define STUB_ENTRY(n) // done in the .s file
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp
new file mode 100644
index 0000000000..0c2bdcdcbb
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp
@@ -0,0 +1,183 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xptcprivate.h"
+
+#if (_MIPS_SIM != _ABIN32) && (_MIPS_SIM != _ABI64)
+#error "This code is for MIPS n32/n64 only"
+#endif
+
+/*
+ * This is for MIPS n32/n64 ABI
+ *
+ * When we're called, the "gp" registers are stored in gprData and
+ * the "fp" registers are stored in fprData. There are 8 regs
+ * available which correspond to the first 7 parameters of the
+ * function and the "this" pointer. If there are additional parms,
+ * they are stored on the stack at address "args".
+ *
+ */
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args,
+ uint64_t *gprData, double *fprData)
+{
+#define PARAM_GPR_COUNT 7
+#define PARAM_FPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint64_t* ap = args;
+ uint32_t iCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (iCount < PARAM_GPR_COUNT)
+ iCount++;
+ else
+ ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*)gprData[iCount++];
+ else
+ dp->val.p = (void*)*ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (int8_t)gprData[iCount++];
+ else
+ dp->val.i8 = (int8_t)*ap++;
+ break;
+
+ case nsXPTType::T_I16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (int16_t)gprData[iCount++];
+ else
+ dp->val.i16 = (int16_t)*ap++;
+ break;
+
+ case nsXPTType::T_I32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (int32_t)gprData[iCount++];
+ else
+ dp->val.i32 = (int32_t)*ap++;
+ break;
+
+ case nsXPTType::T_I64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (int64_t)gprData[iCount++];
+ else
+ dp->val.i64 = (int64_t)*ap++;
+ break;
+
+ case nsXPTType::T_U8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (uint8_t)gprData[iCount++];
+ else
+ dp->val.u8 = (uint8_t)*ap++;
+ break;
+
+ case nsXPTType::T_U16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (uint16_t)gprData[iCount++];
+ else
+ dp->val.u16 = (uint16_t)*ap++;
+ break;
+
+ case nsXPTType::T_U32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (uint32_t)gprData[iCount++];
+ else
+ dp->val.u32 = (uint32_t)*ap++;
+ break;
+
+ case nsXPTType::T_U64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (uint64_t)gprData[iCount++];
+ else
+ dp->val.u64 = (uint64_t)*ap++;
+ break;
+
+ case nsXPTType::T_FLOAT:
+ // the float data formate must not be converted!
+ // Just only copy without conversion.
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.f = *(float*)&fprData[iCount++];
+ else
+ dp->val.f = *((float*)ap++);
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.d = (double)fprData[iCount++];
+ else
+ dp->val.d = *((double*)ap++);
+ break;
+
+ case nsXPTType::T_BOOL:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (bool)gprData[iCount++];
+ else
+ dp->val.b = (bool)*ap++;
+ break;
+
+ case nsXPTType::T_CHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char)gprData[iCount++];
+ else
+ dp->val.c = (char)*ap++;
+ break;
+
+ case nsXPTType::T_WCHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t)gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t)*ap++;
+ break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+#define STUB_ENTRY(n) /* defined in the assembly file */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp
new file mode 100644
index 0000000000..f833a7d902
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp
@@ -0,0 +1,141 @@
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if _HPUX
+#error "This code is for HP-PA RISC 32 bit mode only"
+#endif
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint32_t* args, uint32_t* floatargs)
+{
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU;
+
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ int32_t regwords = 1; /* self pointer is not in the variant records */
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ for(i = 0; i < paramCount; ++i, --args)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ MOZ_CRASH("NYI: support implicit JSContext*, bug 1475699");
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *args;
+ ++regwords;
+ continue;
+ }
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) args); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) args); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) args); break;
+ case nsXPTType::T_DOUBLE :
+ if (regwords & 1)
+ {
+ ++regwords; /* align on double word */
+ --args;
+ }
+ if (regwords == 0 || regwords == 2)
+ {
+ dp->val.d=*((double*) (floatargs + regwords));
+ --args;
+ }
+ else
+ {
+ dp->val.d = *((double*) --args);
+ }
+ regwords += 2;
+ continue;
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 :
+ if (regwords & 1)
+ {
+ ++regwords; /* align on double word */
+ --args;
+ }
+ ((DU *)dp)->lo = *((uint32_t*) args);
+ ((DU *)dp)->hi = *((uint32_t*) --args);
+ regwords += 2;
+ continue;
+ case nsXPTType::T_FLOAT :
+ if (regwords >= 4)
+ dp->val.f = *((float*) args);
+ else
+ dp->val.f = *((float*) floatargs+4+regwords);
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*) args); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*) args); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*) args); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*) args); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*) args); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) args); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ ++regwords;
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t) methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(int);
+
+#ifdef __GNUC__
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ /* Save arg0 in its stack slot. This assumes the frame size is 64. */ \
+ __asm__ __volatile__ ("STW %r26, -36-64(%sp)"); \
+ return SharedStub(n); \
+}
+#else
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ return SharedStub(n); \
+}
+#endif
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp
new file mode 100644
index 0000000000..5bbb6f9e5f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp
@@ -0,0 +1,280 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// Prior to POWER8, all 64-bit Power ISA systems used ELF v1 ABI, found
+// here:
+// https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html
+// and in particular:
+// https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-CALL
+// Little-endian ppc64le, however, uses ELF v2 ABI, which is here:
+// http://openpowerfoundation.org/wp-content/uploads/resources/leabi/leabi-20170510.pdf
+// and in particular section 2.2, page 22. However, most big-endian ppc64
+// systems still use ELF v1, so this file should support both.
+//
+// Both ABIs pass the first 8 integral parameters and the first 13 floating
+// point parameters in registers r3-r10 and f1-f13. No stack space is
+// allocated for these by the caller. The rest of the parameters are passed
+// in the caller's stack area. The stack pointer must stay 16-byte aligned.
+
+const uint32_t GPR_COUNT = 7;
+const uint32_t FPR_COUNT = 13;
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gpregs[]' contains the arguments passed in integer registers
+// - 'fpregs[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+//
+// Both ABIs use the same register assignment strategy, as per this
+// example from V1 ABI section 3.2.3 and V2 ABI section 2.2.3.2 [page 43]:
+//
+// typedef struct {
+// int a;
+// double dd;
+// } sparm;
+// sparm s, t;
+// int c, d, e;
+// long double ld;
+// double ff, gg, hh;
+//
+// x = func(c, ff, d, ld, s, gg, t, e, hh);
+//
+// Parameter Register Offset in parameter save area
+// c r3 0-7 (not stored in parameter save area)
+// ff f1 8-15 (not stored)
+// d r5 16-23 (not stored)
+// ld f2,f3 24-39 (not stored)
+// s r8,r9 40-55 (not stored)
+// gg f4 56-63 (not stored)
+// t (none) 64-79 (stored in parameter save area)
+// e (none) 80-87 (stored)
+// hh f5 88-95 (not stored)
+//
+// i.e., each successive FPR usage skips a GPR, but not the other way around.
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex,
+ uint64_t * args, uint64_t * gpregs, double *fpregs)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint32_t paramCount;
+ uint32_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint64_t* ap = args;
+ // |that| is implicit in the calling convention; we really do start at the
+ // first GPR (as opposed to x86_64).
+ uint32_t nr_gpr = 0;
+ uint32_t nr_fpr = 0;
+ uint64_t value;
+
+ for(i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (nr_gpr < GPR_COUNT)
+ nr_gpr++;
+ else
+ ap++;
+ }
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT) {
+ dp->val.d = fpregs[nr_fpr++];
+ // Even if we have enough FPRs, still skip space in
+ // the parameter area if we ran out of placeholder GPRs.
+ if (nr_gpr < GPR_COUNT) {
+ nr_gpr++;
+ } else {
+ ap++;
+ }
+ } else {
+ dp->val.d = *(double*)ap++;
+ }
+ continue;
+ }
+ if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT) {
+ // Single-precision floats are passed in FPRs too.
+ dp->val.f = (float)fpregs[nr_fpr++];
+ if (nr_gpr < GPR_COUNT) {
+ nr_gpr++;
+ } else {
+ ap++;
+ }
+ } else {
+#ifdef __LITTLE_ENDIAN__
+ dp->val.f = *(float*)ap++;
+#else
+ // Big endian needs adjustment to point to the least
+ // significant word.
+ float* p = (float*)ap;
+ p++;
+ dp->val.f = *p;
+ ap++;
+#endif
+ }
+ continue;
+ }
+ if (nr_gpr < GPR_COUNT)
+ value = gpregs[nr_gpr++];
+ else
+ value = *ap++;
+
+ if (param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*) value;
+ continue;
+ }
+
+ switch (type) {
+ case nsXPTType::T_I8: dp->val.i8 = (int8_t) value; break;
+ case nsXPTType::T_I16: dp->val.i16 = (int16_t) value; break;
+ case nsXPTType::T_I32: dp->val.i32 = (int32_t) value; break;
+ case nsXPTType::T_I64: dp->val.i64 = (int64_t) value; break;
+ case nsXPTType::T_U8: dp->val.u8 = (uint8_t) value; break;
+ case nsXPTType::T_U16: dp->val.u16 = (uint16_t) value; break;
+ case nsXPTType::T_U32: dp->val.u32 = (uint32_t) value; break;
+ case nsXPTType::T_U64: dp->val.u64 = (uint64_t) value; break;
+ case nsXPTType::T_BOOL: dp->val.b = (bool) value; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) value; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break;
+
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t) methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+// Load r11 with the constant 'n' and branch to SharedStub().
+//
+// As G++3 ABI contains the length of the functionname in the mangled
+// name, it is difficult to get a generic assembler mechanism like
+// in the G++ 2.95 case.
+// XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
+// however, it's quick, dirty, and'll break when the ABI changes on
+// us, which is what we want ;-).
+// Create names would be like:
+// _ZN14nsXPTCStubBase5Stub1Ev
+// _ZN14nsXPTCStubBase6Stub12Ev
+// _ZN14nsXPTCStubBase7Stub123Ev
+// _ZN14nsXPTCStubBase8Stub1234Ev
+// etc.
+// Use assembler directives to get the names right.
+
+#if _CALL_ELF == 2
+# define STUB_ENTRY(n) \
+__asm__ ( \
+ ".section \".text\" \n\t" \
+ ".align 2 \n\t" \
+ ".if "#n" < 10 \n\t" \
+ ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
+ "0: addis 2,12,.TOC.-0b@ha \n\t" \
+ "addi 2,2,.TOC.-0b@l \n\t" \
+ ".localentry _ZN14nsXPTCStubBase5Stub"#n"Ev,.-_ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ \
+ ".elseif "#n" < 100 \n\t" \
+ ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ "0: addis 2,12,.TOC.-0b@ha \n\t" \
+ "addi 2,2,.TOC.-0b@l \n\t" \
+ ".localentry _ZN14nsXPTCStubBase6Stub"#n"Ev,.-_ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ \
+ ".elseif "#n" < 1000 \n\t" \
+ ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
+ "0: addis 2,12,.TOC.-0b@ha \n\t" \
+ "addi 2,2,.TOC.-0b@l \n\t" \
+ ".localentry _ZN14nsXPTCStubBase7Stub"#n"Ev,.-_ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ \
+ ".else \n\t" \
+ ".err \"stub number "#n" >= 1000 not yet supported\"\n" \
+ ".endif \n\t" \
+ \
+ "li 11,"#n" \n\t" \
+ "b SharedStub \n" \
+);
+#else
+# define STUB_ENTRY(n) \
+__asm__ ( \
+ ".section \".toc\",\"aw\" \n\t" \
+ ".section \".text\" \n\t" \
+ ".align 2 \n\t" \
+ ".if "#n" < 10 \n\t" \
+ ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ ".section \".opd\",\"aw\" \n\t" \
+ ".align 3 \n\t" \
+"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
+ ".quad ._ZN14nsXPTCStubBase5Stub"#n"Ev,.TOC.@tocbase \n\t" \
+ ".previous \n\t" \
+ ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \
+"._ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
+ \
+ ".elseif "#n" < 100 \n\t" \
+ ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ ".section \".opd\",\"aw\" \n\t" \
+ ".align 3 \n\t" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ ".quad ._ZN14nsXPTCStubBase6Stub"#n"Ev,.TOC.@tocbase \n\t" \
+ ".previous \n\t" \
+ ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
+"._ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ \
+ ".elseif "#n" < 1000 \n\t" \
+ ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ ".section \".opd\",\"aw\" \n\t" \
+ ".align 3 \n\t" \
+"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
+ ".quad ._ZN14nsXPTCStubBase7Stub"#n"Ev,.TOC.@tocbase \n\t" \
+ ".previous \n\t" \
+ ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \
+"._ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
+ \
+ ".else \n\t" \
+ ".err \"stub number "#n" >= 1000 not yet supported\"\n" \
+ ".endif \n\t" \
+ \
+ "li 11,"#n" \n\t" \
+ "b SharedStub \n" \
+);
+#endif
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp
new file mode 100644
index 0000000000..28eee7c394
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp
@@ -0,0 +1,181 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(AIX)
+
+/*
+ For PPC (AIX & MAC), the first 8 integral and the first 13 f.p. parameters
+ arrive in a separate chunk of data that has been loaded from the registers.
+ The args pointer has been set to the start of the parameters BEYOND the ones
+ arriving in registers
+*/
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args, uint32_t *gprData, double *fprData)
+{
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo; // have to move 64 bit entities as 32 bit halves since
+ } DU; // stack slots are not guaranteed 16 byte aligned
+
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint32_t* ap = args;
+ uint32_t iCount = 0;
+ uint32_t fpCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (iCount < PARAM_GPR_COUNT)
+ iCount++;
+ else
+ ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*) gprData[iCount++];
+ else
+ dp->val.p = (void*) *ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (int8_t) gprData[iCount++];
+ else
+ dp->val.i8 = (int8_t) *ap++;
+ break;
+ case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (int16_t) gprData[iCount++];
+ else
+ dp->val.i16 = (int16_t) *ap++;
+ break;
+ case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (int32_t) gprData[iCount++];
+ else
+ dp->val.i32 = (int32_t) *ap++;
+ break;
+ case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->hi = (int32_t) gprData[iCount++];
+ else
+ ((DU *)dp)->hi = (int32_t) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->lo = (uint32_t) gprData[iCount++];
+ else
+ ((DU *)dp)->lo = (uint32_t) *ap++;
+ break;
+ case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (uint8_t) gprData[iCount++];
+ else
+ dp->val.u8 = (uint8_t) *ap++;
+ break;
+ case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (uint16_t) gprData[iCount++];
+ else
+ dp->val.u16 = (uint16_t) *ap++;
+ break;
+ case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (uint32_t) gprData[iCount++];
+ else
+ dp->val.u32 = (uint32_t) *ap++;
+ break;
+ case nsXPTType::T_U64 : if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->hi = (uint32_t) gprData[iCount++];
+ else
+ ((DU *)dp)->hi = (uint32_t) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->lo = (uint32_t) gprData[iCount++];
+ else
+ ((DU *)dp)->lo = (uint32_t) *ap++;
+ break;
+ case nsXPTType::T_FLOAT : if (fpCount < 13) {
+ dp->val.f = (float) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else
+ dp->val.f = *((float*) ap++);
+ break;
+ case nsXPTType::T_DOUBLE : if (fpCount < 13) {
+ dp->val.d = (double) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else {
+ dp->val.f = *((double*) ap);
+ ap += 2;
+ }
+ break;
+ case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (bool) gprData[iCount++];
+ else
+ dp->val.b = (bool) *ap++;
+ break;
+ case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char) gprData[iCount++];
+ else
+ dp->val.c = (char) *ap++;
+ break;
+ case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t) gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t) *ap++;
+ break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+#define STUB_ENTRY(n)
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* AIX */
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp
new file mode 100644
index 0000000000..297ed3e3bb
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp
@@ -0,0 +1,168 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(AIX)
+
+/*
+ For PPC (AIX & MAC), the first 8 integral and the first 13 f.p. parameters
+ arrive in a separate chunk of data that has been loaded from the registers.
+ The args pointer has been set to the start of the parameters BEYOND the ones
+ arriving in registers
+*/
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args, uint64_t *gprData, double *fprData)
+{
+
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint64_t* ap = args;
+ uint32_t iCount = 0;
+ uint32_t fpCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (iCount < PARAM_GPR_COUNT)
+ iCount++;
+ else
+ ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*) gprData[iCount++];
+ else
+ dp->val.p = (void*) *ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (int8_t) gprData[iCount++];
+ else
+ dp->val.i8 = (int8_t) *ap++;
+ break;
+ case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (int16_t) gprData[iCount++];
+ else
+ dp->val.i16 = (int16_t) *ap++;
+ break;
+ case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (int32_t) gprData[iCount++];
+ else
+ dp->val.i32 = (int32_t) *ap++;
+ break;
+ case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (int64_t) gprData[iCount++];
+ else
+ dp->val.i64 = (int64_t) *ap++;
+ break;
+ case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (uint8_t) gprData[iCount++];
+ else
+ dp->val.u8 = (uint8_t) *ap++;
+ break;
+ case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (uint16_t) gprData[iCount++];
+ else
+ dp->val.u16 = (uint16_t) *ap++;
+ break;
+ case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (uint32_t) gprData[iCount++];
+ else
+ dp->val.u32 = (uint32_t) *ap++;
+ break;
+ case nsXPTType::T_U64 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (uint64_t) gprData[iCount++];
+ else
+ dp->val.u64 = (uint64_t) *ap++;
+ break;
+ case nsXPTType::T_FLOAT : if (fpCount < 13) {
+ dp->val.f = (float) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else
+ dp->val.f = *((float*) ap++);
+ break;
+ case nsXPTType::T_DOUBLE : if (fpCount < 13) {
+ dp->val.d = (double) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else {
+ dp->val.f = *((double*) ap);
+ ap += 2;
+ }
+ break;
+ case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (bool) gprData[iCount++];
+ else
+ dp->val.b = (bool) *ap++;
+ break;
+ case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char) gprData[iCount++];
+ else
+ dp->val.c = (char) *ap++;
+ break;
+ case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t) gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t) *ap++;
+ break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+#define STUB_ENTRY(n)
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* AIX */
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp
new file mode 100644
index 0000000000..e644428f77
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp
@@ -0,0 +1,211 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral
+// parameters and the first 8 floating point parameters in registers
+// (r3-r10 and f1-f8), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area. The stack pointer has to retain 16-byte alignment, longlongs
+// and doubles are aligned on 8-byte boundaries.
+#ifndef __NO_FPRS__
+#define GPR_COUNT 8
+#define FPR_COUNT 8
+#else
+#define GPR_COUNT 8
+#endif
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gprData[]' contains the arguments passed in integer registers
+// - 'fprData[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self,
+ uint32_t methodIndex,
+ uint32_t* args,
+ uint32_t *gprData,
+ double *fprData)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info = nullptr;
+ uint32_t paramCount;
+ uint32_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (! info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint32_t* ap = args;
+ uint32_t gpr = 1; // skip one GPR register
+#ifndef __NO_FPRS__
+ uint32_t fpr = 0;
+#endif
+ uint32_t tempu32;
+ uint64_t tempu64;
+
+ for(i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (gpr < GPR_COUNT)
+ gpr++;
+ else
+ ap++;
+ }
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+#ifndef __NO_FPRS__
+ if (fpr < FPR_COUNT)
+ dp->val.d = fprData[fpr++];
+#else
+ if (gpr & 1)
+ gpr++;
+ if (gpr + 1 < GPR_COUNT) {
+ dp->val.d = *(double*) &gprData[gpr];
+ gpr += 2;
+ }
+#endif
+ else {
+ if ((uint32_t) ap & 4) ap++; // doubles are 8-byte aligned on stack
+ dp->val.d = *(double*) ap;
+ ap += 2;
+ }
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+#ifndef __NO_FPRS__
+ if (fpr < FPR_COUNT)
+ dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles
+#else
+ if (gpr < GPR_COUNT)
+ dp->val.f = *(float*) &gprData[gpr++];
+#endif
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && (type == nsXPTType::T_I64
+ || type == nsXPTType::T_U64)) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((gpr + 1) < GPR_COUNT) {
+ tempu64 = *(uint64_t*) &gprData[gpr];
+ gpr += 2;
+ }
+ else {
+ if ((uint32_t) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(uint64_t*) ap;
+ ap += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ tempu32 = gprData[gpr++];
+ else
+ tempu32 = *ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic()) {
+ if (type == nsXPTType::T_JSVAL)
+ dp->val.p = *((void**) tempu32);
+ else
+ dp->val.p = (void*) tempu32;
+ continue;
+ }
+
+ switch(type) {
+ case nsXPTType::T_I8: dp->val.i8 = (int8_t) tempu32; break;
+ case nsXPTType::T_I16: dp->val.i16 = (int16_t) tempu32; break;
+ case nsXPTType::T_I32: dp->val.i32 = (int32_t) tempu32; break;
+ case nsXPTType::T_I64: dp->val.i64 = (int64_t) tempu64; break;
+ case nsXPTType::T_U8: dp->val.u8 = (uint8_t) tempu32; break;
+ case nsXPTType::T_U16: dp->val.u16 = (uint16_t) tempu32; break;
+ case nsXPTType::T_U32: dp->val.u32 = (uint32_t) tempu32; break;
+ case nsXPTType::T_U64: dp->val.u64 = (uint64_t) tempu64; break;
+ case nsXPTType::T_BOOL: dp->val.b = (bool) tempu32; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break;
+
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex,
+ info,
+ paramBuffer);
+
+ return result;
+}
+
+// Load r11 with the constant 'n' and branch to SharedStub().
+//
+// XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
+// however, it's quick, dirty, and'll break when the ABI changes on
+// us, which is what we want ;-).
+
+// gcc-3 version
+//
+// As G++3 ABI contains the length of the functionname in the mangled
+// name, it is difficult to get a generic assembler mechanism like
+// in the G++ 2.95 case.
+// Create names would be like:
+// _ZN14nsXPTCStubBase5Stub1Ev
+// _ZN14nsXPTCStubBase6Stub12Ev
+// _ZN14nsXPTCStubBase7Stub123Ev
+// _ZN14nsXPTCStubBase8Stub1234Ev
+// etc.
+// Use assembler directives to get the names right...
+
+# define STUB_ENTRY(n) \
+__asm__ ( \
+ ".align 2 \n\t" \
+ ".if "#n" < 10 \n\t" \
+ ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
+ \
+ ".elseif "#n" < 100 \n\t" \
+ ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ \
+ ".elseif "#n" < 1000 \n\t" \
+ ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
+ \
+ ".else \n\t" \
+ ".err \"stub number "#n" >= 1000 not yet supported\"\n" \
+ ".endif \n\t" \
+ \
+ "li 11,"#n" \n\t" \
+ "b SharedStub@local \n" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp
new file mode 100644
index 0000000000..121ff48556
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp
@@ -0,0 +1,194 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral
+// parameters and the first 8 floating point parameters in registers
+// (r3-r10 and f1-f8), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area. The stack pointer has to retain 16-byte alignment, longlongs
+// and doubles are aligned on 8-byte boundaries.
+
+#define GPR_COUNT 8
+#define FPR_COUNT 8
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gprData[]' contains the arguments passed in integer registers
+// - 'fprData[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self,
+ uint32_t methodIndex,
+ uint32_t* args,
+ uint32_t *gprData,
+ double *fprData)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info = nullptr;
+ uint32_t paramCount;
+ uint32_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (! info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint32_t* ap = args;
+ uint32_t gpr = 1; // skip one GPR register
+ uint32_t fpr = 0;
+ uint32_t tempu32;
+ uint64_t tempu64;
+
+ for(i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (gpr < GPR_COUNT)
+ gpr++;
+ else
+ ap++;
+ }
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ dp->val.d = fprData[fpr++];
+ else {
+ if ((uint32_t) ap & 4) ap++; // doubles are 8-byte aligned on stack
+ dp->val.d = *(double*) ap;
+ ap += 2;
+ }
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && (type == nsXPTType::T_I64
+ || type == nsXPTType::T_U64)) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((gpr + 1) < GPR_COUNT) {
+ tempu64 = *(uint64_t*) &gprData[gpr];
+ gpr += 2;
+ }
+ else {
+ if ((uint32_t) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(uint64_t*) ap;
+ ap += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ tempu32 = gprData[gpr++];
+ else
+ tempu32 = *ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic()) {
+ if (type == nsXPTType::T_JSVAL)
+ dp->val.p = *((void**) tempu32);
+ else
+ dp->val.p = (void*) tempu32;
+ continue;
+ }
+
+ switch(type) {
+ case nsXPTType::T_I8: dp->val.i8 = (int8_t) tempu32; break;
+ case nsXPTType::T_I16: dp->val.i16 = (int16_t) tempu32; break;
+ case nsXPTType::T_I32: dp->val.i32 = (int32_t) tempu32; break;
+ case nsXPTType::T_I64: dp->val.i64 = (int64_t) tempu64; break;
+ case nsXPTType::T_U8: dp->val.u8 = (uint8_t) tempu32; break;
+ case nsXPTType::T_U16: dp->val.u16 = (uint16_t) tempu32; break;
+ case nsXPTType::T_U32: dp->val.u32 = (uint32_t) tempu32; break;
+ case nsXPTType::T_U64: dp->val.u64 = (uint64_t) tempu64; break;
+ case nsXPTType::T_BOOL: dp->val.b = (bool) tempu32; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break;
+
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex,
+ info,
+ paramBuffer);
+
+ return result;
+}
+
+// Load r11 with the constant 'n' and branch to SharedStub().
+//
+// XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
+// however, it's quick, dirty, and'll break when the ABI changes on
+// us, which is what we want ;-).
+
+
+// gcc-3 version
+//
+// As G++3 ABI contains the length of the functionname in the mangled
+// name, it is difficult to get a generic assembler mechanism like
+// in the G++ 2.95 case.
+// Create names would be like:
+// _ZN14nsXPTCStubBase5Stub1Ev
+// _ZN14nsXPTCStubBase6Stub12Ev
+// _ZN14nsXPTCStubBase7Stub123Ev
+// _ZN14nsXPTCStubBase8Stub1234Ev
+// etc.
+// Use assembler directives to get the names right...
+
+# define STUB_ENTRY(n) \
+__asm__ ( \
+ ".align 2 \n\t" \
+ ".if "#n" < 10 \n\t" \
+ ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
+ \
+ ".elseif "#n" < 100 \n\t" \
+ ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ \
+ ".elseif "#n" < 1000 \n\t" \
+ ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
+ \
+ ".else \n\t" \
+ ".err \"stub number "#n" >= 1000 not yet supported\"\n" \
+ ".endif \n\t" \
+ \
+ "li 11,"#n" \n\t" \
+ "b SharedStub@local \n" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp
new file mode 100644
index 0000000000..43b4f029c6
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp
@@ -0,0 +1,150 @@
+/* -*- Mode: C -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xptcprivate.h"
+
+/* Under the Mac OS X PowerPC ABI, the first 8 integer and 13 floating point
+ * parameters are delivered in registers and are not on the stack, although
+ * stack space is allocated for them. The integer parameters are delivered
+ * in GPRs r3 through r10. The first 8 words of the parameter area on the
+ * stack shadow these registers. A word will either be in a register or on
+ * the stack, but not in both. Although the first floating point parameters
+ * are passed in floating point registers, GPR space and stack space is
+ * reserved for them as well.
+ *
+ * SharedStub has passed pointers to the parameter section of the stack
+ * and saved copies of the GPRs and FPRs used for parameter passing. We
+ * don't care about the first parameter (which is delivered here as the self
+ * pointer), so SharedStub pointed us past that. argsGPR thus points to GPR
+ * r4 (corresponding to the first argument after the self pointer) and
+ * argsStack points to the parameter section of the caller's stack frame
+ * reserved for the same argument. This way, it is possible to reference
+ * either argsGPR or argsStack with the same index.
+ *
+ * Contrary to the assumption made by the previous implementation, the
+ * Mac OS X PowerPC ABI doesn't impose any special alignment restrictions on
+ * parameter sections of stacks. Values that are 64 bits wide appear on the
+ * stack without any special padding.
+ *
+ * See also xptcstubs_asm_ppc_darwin.s.m4:_SharedStub.
+ *
+ * ABI reference:
+ * http://developer.apple.com/documentation/DeveloperTools/Conceptual/
+ * MachORuntime/PowerPCConventions/chapter_3_section_1.html */
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(
+ nsXPTCStubBase *self,
+ uint32_t methodIndex,
+ uint32_t *argsStack,
+ uint32_t *argsGPR,
+ double *argsFPR) {
+#define PARAM_FPR_COUNT 13
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo *methodInfo;
+ uint8_t paramCount;
+ uint8_t i;
+ uint32_t argIndex = 0;
+ uint32_t fprIndex = 0;
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU;
+
+ NS_ASSERTION(self, "no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &methodInfo);
+ NS_ASSERTION(methodInfo, "no method info");
+
+ paramCount = methodInfo->GetParamCount();
+
+ for(i = 0; i < paramCount; i++, argIndex++) {
+ const nsXPTParamInfo &param = methodInfo->GetParam(i);
+ const nsXPTType &type = param.GetType();
+ nsXPTCMiniVariant *dp = &paramBuffer[i];
+ uint32_t theParam;
+
+ if(argIndex < PARAM_GPR_COUNT)
+ theParam = argsGPR[argIndex];
+ else
+ theParam = argsStack[argIndex];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ dp->val.p = (void *) theParam;
+ else {
+ switch(type) {
+ case nsXPTType::T_I8:
+ dp->val.i8 = (int8_t) theParam;
+ break;
+ case nsXPTType::T_I16:
+ dp->val.i16 = (int16_t) theParam;
+ break;
+ case nsXPTType::T_I32:
+ dp->val.i32 = (int32_t) theParam;
+ break;
+ case nsXPTType::T_U8:
+ dp->val.u8 = (uint8_t) theParam;
+ break;
+ case nsXPTType::T_U16:
+ dp->val.u16 = (uint16_t) theParam;
+ break;
+ case nsXPTType::T_U32:
+ dp->val.u32 = (uint32_t) theParam;
+ break;
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U64:
+ ((DU *)dp)->hi = (uint32_t) theParam;
+ if(++argIndex < PARAM_GPR_COUNT)
+ ((DU *)dp)->lo = (uint32_t) argsGPR[argIndex];
+ else
+ ((DU *)dp)->lo = (uint32_t) argsStack[argIndex];
+ break;
+ case nsXPTType::T_BOOL:
+ dp->val.b = (bool) theParam;
+ break;
+ case nsXPTType::T_CHAR:
+ dp->val.c = (char) theParam;
+ break;
+ case nsXPTType::T_WCHAR:
+ dp->val.wc = (wchar_t) theParam;
+ break;
+ case nsXPTType::T_FLOAT:
+ if(fprIndex < PARAM_FPR_COUNT)
+ dp->val.f = (float) argsFPR[fprIndex++];
+ else
+ dp->val.f = *(float *) &argsStack[argIndex];
+ break;
+ case nsXPTType::T_DOUBLE:
+ if(fprIndex < PARAM_FPR_COUNT)
+ dp->val.d = argsFPR[fprIndex++];
+ else
+ dp->val.d = *(double *) &argsStack[argIndex];
+ argIndex++;
+ break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+ }
+
+ nsresult result = self->mOuter->
+ CallMethod((uint16_t)methodIndex, methodInfo, paramBuffer);
+
+ return result;
+}
+
+#define STUB_ENTRY(n)
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_riscv64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_riscv64.cpp
new file mode 100644
index 0000000000..b50fc23ffd
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_riscv64.cpp
@@ -0,0 +1,160 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if defined(__riscv_float_abi_soft)
+# error "Not support soft float ABI"
+#endif
+
+#include "xptcprivate.h"
+
+extern "C" nsresult ATTRIBUTE_USED PrepareAndDispatch(nsXPTCStubBase* self,
+ uint32_t methodIndex,
+ uint64_t* args,
+ uint64_t* gpregs,
+ double* fpregs) {
+ static const uint32_t GPR_COUNT = 8;
+ static const uint32_t FPR_COUNT = 8;
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+
+ uint32_t paramCount = info->GetParamCount();
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint64_t* ap = args;
+ uint32_t nr_gpr = 1; // skip one GPR register for 'self'
+ uint32_t nr_fpr = 0;
+ uint64_t value;
+
+ for (uint32_t i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (nr_gpr < GPR_COUNT)
+ nr_gpr++;
+ else
+ ap++;
+ }
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT) {
+ dp->val.d = fpregs[nr_fpr++];
+ } else {
+ dp->val.d = *(double*)ap++;
+ }
+ continue;
+ }
+
+ if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT) {
+ dp->val.d = fpregs[nr_fpr++];
+ } else {
+ dp->val.f = *(float*)ap++;
+ }
+ continue;
+ }
+
+ if (nr_gpr < GPR_COUNT) {
+ value = gpregs[nr_gpr++];
+ } else {
+ value = *ap++;
+ }
+
+ if (param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*)value;
+ continue;
+ }
+
+ switch (type) {
+ case nsXPTType::T_I8:
+ dp->val.i8 = (int8_t)value;
+ break;
+ case nsXPTType::T_I16:
+ dp->val.i16 = (int16_t)value;
+ break;
+ case nsXPTType::T_I32:
+ dp->val.i32 = (int32_t)value;
+ break;
+ case nsXPTType::T_I64:
+ dp->val.i64 = (int64_t)value;
+ break;
+ case nsXPTType::T_U8:
+ dp->val.u8 = (uint8_t)value;
+ break;
+ case nsXPTType::T_U16:
+ dp->val.u16 = (uint16_t)value;
+ break;
+ case nsXPTType::T_U32:
+ dp->val.u32 = (uint32_t)value;
+ break;
+ case nsXPTType::T_U64:
+ dp->val.u64 = (uint64_t)value;
+ break;
+ case nsXPTType::T_BOOL:
+ dp->val.b = (bool)(uint8_t)value;
+ break;
+ case nsXPTType::T_CHAR:
+ dp->val.c = (char)value;
+ break;
+ case nsXPTType::T_WCHAR:
+ dp->val.wc = (wchar_t)value;
+ break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result =
+ self->mOuter->CallMethod((uint16_t)methodIndex, info, paramBuffer);
+
+ return result;
+}
+
+// Load t0 with the constant 'n' and branch to SharedStub().
+// clang-format off
+#define STUB_ENTRY(n) \
+ __asm__( \
+ ".text\n\t" \
+ ".if "#n" < 10 \n\t" \
+ ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ ".hidden _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \
+ "_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
+ ".elseif "#n" < 100 \n\t" \
+ ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ ".hidden _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
+ "_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ ".elseif "#n" < 1000 \n\t" \
+ ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ ".hidden _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \
+ "_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
+ ".else \n\t" \
+ ".err \"stub number "#n" >= 1000 not yet supported\"\n" \
+ ".endif \n\t" \
+ "li t0, "#n" \n\t" \
+ "j SharedStub \n" \
+ ".if "#n" < 10\n\t" \
+ ".size _ZN14nsXPTCStubBase5Stub"#n"Ev,.-_ZN14nsXPTCStubBase5Stub"#n"Ev\n\t" \
+ ".elseif "#n" < 100\n\t" \
+ ".size _ZN14nsXPTCStubBase6Stub"#n"Ev,.-_ZN14nsXPTCStubBase6Stub"#n"Ev\n\t" \
+ ".else\n\t" \
+ ".size _ZN14nsXPTCStubBase7Stub"#n"Ev,.-_ZN14nsXPTCStubBase7Stub"#n"Ev\n\t" \
+ ".endif" \
+);
+// clang-format on
+
+#define SENTINEL_ENTRY(n) \
+ nsresult nsXPTCStubBase::Sentinel##n() { \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+ }
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp
new file mode 100644
index 0000000000..79ecc6ab89
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args)
+{
+
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint64_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext)
+ ap++;
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_BOOL : dp->val.b = *((int64_t*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((uint64_t*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((int64_t*) ap); break;
+ case nsXPTType::T_I8 : dp->val.i8 = *((int64_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int64_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int64_t*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint64_t*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint64_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint64_t*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*) ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = ((float*) ap)[1]; break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(int, int*);
+
+/*
+ * Avoid GCC stack protector to wipe out input registers since the compiler
+ * thinks the function takes no arguments.
+ */
+#ifndef nostackprotector
+#define nostackprotector __attribute__((__optimize__("no-stack-protector")))
+#endif
+
+#define STUB_ENTRY(n) \
+nsresult nostackprotector nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp
new file mode 100644
index 0000000000..33b839ffa4
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp
@@ -0,0 +1,103 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTInterfaceInfo* iface_info = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (type == nsXPTType::T_JSVAL)
+ dp->val.p = *((void**) *ap);
+ else
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_DOUBLE :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi;
+ ((DU *)dp)->lo = ((DU *)ap)->lo;
+ ap++;
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*)ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*)ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp
new file mode 100644
index 0000000000..33b839ffa4
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp
@@ -0,0 +1,103 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTInterfaceInfo* iface_info = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (type == nsXPTType::T_JSVAL)
+ dp->val.p = *((void**) *ap);
+ else
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_DOUBLE :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi;
+ ((DU *)dp)->lo = ((DU *)ap)->lo;
+ ap++;
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*)ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*)ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp
new file mode 100644
index 0000000000..488c3e7895
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext)
+ ap++;
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (type == nsXPTType::T_JSVAL)
+ dp->val.p = *((void**) *ap);
+ else
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_DOUBLE :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi;
+ ((DU *)dp)->lo = ((DU *)ap)->lo;
+ ap++;
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*)ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*)ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp
new file mode 100644
index 0000000000..48beb32aff
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp
@@ -0,0 +1,183 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Implement shared vtbl methods.
+
+// Keep this in sync with the linux version.
+
+#include "xptcprivate.h"
+
+// The Darwin/x86-64 ABI passes the first 6 integer parameters and the
+// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,
+// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area.
+
+const uint32_t GPR_COUNT = 6;
+const uint32_t FPR_COUNT = 8;
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gpregs[]' contains the arguments passed in integer registers
+// - 'fpregs[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex,
+ uint64_t * args, uint64_t * gpregs, double *fpregs)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint32_t paramCount;
+ uint32_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint64_t* ap = args;
+ uint32_t nr_gpr = 1; // skip one GPR register for 'that'
+ uint32_t nr_fpr = 0;
+ uint64_t value;
+
+ for (i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (nr_gpr < GPR_COUNT)
+ nr_gpr++;
+ else
+ ap++;
+ }
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.d = *(double*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ value = gpregs[nr_gpr++];
+ else
+ value = *ap++;
+ }
+
+ if (param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*) value;
+ continue;
+ }
+
+ switch (type) {
+ case nsXPTType::T_I8: dp->val.i8 = (int8_t) value; break;
+ case nsXPTType::T_I16: dp->val.i16 = (int16_t) value; break;
+ case nsXPTType::T_I32: dp->val.i32 = (int32_t) value; break;
+ case nsXPTType::T_I64: dp->val.i64 = (int64_t) value; break;
+ case nsXPTType::T_U8: dp->val.u8 = (uint8_t) value; break;
+ case nsXPTType::T_U16: dp->val.u16 = (uint16_t) value; break;
+ case nsXPTType::T_U32: dp->val.u32 = (uint32_t) value; break;
+ case nsXPTType::T_U64: dp->val.u64 = (uint64_t) value; break;
+ // Cast to uint8_t first, to remove garbage on upper 56 bits.
+ case nsXPTType::T_BOOL: dp->val.b = (bool)(uint8_t) value; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) value; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break;
+
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t) methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+// Darwin/x86-64 uses gcc >= 4.2
+
+#define STUB_ENTRY(n) \
+asm(".section __TEXT,__text\n\t" \
+ ".align 3\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl __ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ "__ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl __ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ "__ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl __ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ "__ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp SharedStub\n\t");
+
+// static nsresult SharedStub(uint32_t methodIndex)
+asm(".section __TEXT,__text\n\t"
+ ".align 3\n\t"
+ "SharedStub:\n\t"
+ // make room for gpregs (48), fpregs (64)
+ "pushq %rbp\n\t"
+ "movq %rsp,%rbp\n\t"
+ "subq $112,%rsp\n\t"
+ // save GP registers
+ "movq %rdi,-112(%rbp)\n\t"
+ "movq %rsi,-104(%rbp)\n\t"
+ "movq %rdx, -96(%rbp)\n\t"
+ "movq %rcx, -88(%rbp)\n\t"
+ "movq %r8 , -80(%rbp)\n\t"
+ "movq %r9 , -72(%rbp)\n\t"
+ "leaq -112(%rbp),%rcx\n\t"
+ // save FP registers
+ "movsd %xmm0,-64(%rbp)\n\t"
+ "movsd %xmm1,-56(%rbp)\n\t"
+ "movsd %xmm2,-48(%rbp)\n\t"
+ "movsd %xmm3,-40(%rbp)\n\t"
+ "movsd %xmm4,-32(%rbp)\n\t"
+ "movsd %xmm5,-24(%rbp)\n\t"
+ "movsd %xmm6,-16(%rbp)\n\t"
+ "movsd %xmm7, -8(%rbp)\n\t"
+ "leaq -64(%rbp),%r8\n\t"
+ // rdi has the 'self' pointer already
+ "movl %eax,%esi\n\t"
+ "leaq 16(%rbp),%rdx\n\t"
+ "call _PrepareAndDispatch\n\t"
+ "leave\n\t"
+ "ret\n\t");
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp
new file mode 100644
index 0000000000..e392365be4
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp
@@ -0,0 +1,209 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Implement shared vtbl methods.
+
+// Keep this in sync with the darwin version.
+
+#include "xptcprivate.h"
+
+// The Linux/x86-64 ABI passes the first 6 integer parameters and the
+// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,
+// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area.
+
+const uint32_t GPR_COUNT = 6;
+const uint32_t FPR_COUNT = 8;
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gpregs[]' contains the arguments passed in integer registers
+// - 'fpregs[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex,
+ uint64_t * args, uint64_t * gpregs, double *fpregs)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+ uint32_t paramCount;
+ uint32_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint64_t* ap = args;
+ uint32_t nr_gpr = 1; // skip one GPR register for 'that'
+ uint32_t nr_fpr = 0;
+ uint64_t value;
+
+ for (i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (nr_gpr < GPR_COUNT)
+ nr_gpr++;
+ else
+ ap++;
+ }
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.d = *(double*)ap++;
+ continue;
+ }
+ if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.f = *(float*)ap++;
+ continue;
+ }
+ if (nr_gpr < GPR_COUNT)
+ value = gpregs[nr_gpr++];
+ else
+ value = *ap++;
+
+ if (param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*) value;
+ continue;
+ }
+
+ switch (type) {
+ case nsXPTType::T_I8: dp->val.i8 = (int8_t) value; break;
+ case nsXPTType::T_I16: dp->val.i16 = (int16_t) value; break;
+ case nsXPTType::T_I32: dp->val.i32 = (int32_t) value; break;
+ case nsXPTType::T_I64: dp->val.i64 = (int64_t) value; break;
+ case nsXPTType::T_U8: dp->val.u8 = (uint8_t) value; break;
+ case nsXPTType::T_U16: dp->val.u16 = (uint16_t) value; break;
+ case nsXPTType::T_U32: dp->val.u32 = (uint32_t) value; break;
+ case nsXPTType::T_U64: dp->val.u64 = (uint64_t) value; break;
+ // Cast to uint8_t first, to remove garbage on upper 56 bits.
+ case nsXPTType::T_BOOL: dp->val.b = (bool)(uint8_t) value; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) value; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break;
+
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t) methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+// Linux/x86-64 uses gcc >= 3.1
+// We don't include .cfi_startproc/endproc directives for the individual stubs
+// because there's no extra CFI bits to define beyond the default CIE.
+#define STUB_ENTRY(n) \
+asm(".section \".text\"\n\t" \
+ ".align 2\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl _ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".hidden _ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".type _ZN14nsXPTCStubBase5Stub" #n "Ev,@function\n" \
+ "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl _ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".hidden _ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".type _ZN14nsXPTCStubBase6Stub" #n "Ev,@function\n" \
+ "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl _ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".hidden _ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".type _ZN14nsXPTCStubBase7Stub" #n "Ev,@function\n" \
+ "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp SharedStub\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".size _ZN14nsXPTCStubBase5Stub" #n "Ev,.-_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".size _ZN14nsXPTCStubBase6Stub" #n "Ev,.-_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".else\n\t" \
+ ".size _ZN14nsXPTCStubBase7Stub" #n "Ev,.-_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".endif");
+
+// static nsresult SharedStub(uint32_t methodIndex)
+asm(".section \".text\"\n\t"
+ ".align 2\n\t"
+ ".type SharedStub,@function\n\t"
+ "SharedStub:\n\t"
+ ".cfi_startproc\n\t"
+ // make room for gpregs (48), fpregs (64)
+ "pushq %rbp\n\t"
+ ".cfi_def_cfa_offset 16\n\t"
+ ".cfi_offset 6, -16\n\t"
+ "movq %rsp,%rbp\n\t"
+ ".cfi_def_cfa_register 6\n\t"
+ "subq $112,%rsp\n\t"
+ // save GP registers
+ "movq %rdi,-112(%rbp)\n\t"
+ "movq %rsi,-104(%rbp)\n\t"
+ "movq %rdx, -96(%rbp)\n\t"
+ "movq %rcx, -88(%rbp)\n\t"
+ "movq %r8 , -80(%rbp)\n\t"
+ "movq %r9 , -72(%rbp)\n\t"
+ ".cfi_offset 5, -24\n\t" // rdi
+ ".cfi_offset 4, -32\n\t" // rsi
+ ".cfi_offset 1, -40\n\t" // rdx
+ ".cfi_offset 2, -48\n\t" // rcx
+ ".cfi_offset 8, -56\n\t" // r8
+ ".cfi_offset 9, -64\n\t" // r9
+ "leaq -112(%rbp),%rcx\n\t"
+ // save FP registers
+ "movsd %xmm0,-64(%rbp)\n\t"
+ "movsd %xmm1,-56(%rbp)\n\t"
+ "movsd %xmm2,-48(%rbp)\n\t"
+ "movsd %xmm3,-40(%rbp)\n\t"
+ "movsd %xmm4,-32(%rbp)\n\t"
+ "movsd %xmm5,-24(%rbp)\n\t"
+ "movsd %xmm6,-16(%rbp)\n\t"
+ "movsd %xmm7, -8(%rbp)\n\t"
+ "leaq -64(%rbp),%r8\n\t"
+ // rdi has the 'self' pointer already
+ "movl %eax,%esi\n\t"
+ "leaq 16(%rbp),%rdx\n\t"
+ "call PrepareAndDispatch@plt\n\t"
+ "leave\n\t"
+ ".cfi_def_cfa 7, 8\n\t"
+ "ret\n\t"
+ ".cfi_endproc\n\t"
+ ".size SharedStub,.-SharedStub");
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/win32/moz.build b/xpcom/reflect/xptcall/md/win32/moz.build
new file mode 100644
index 0000000000..8c169135f4
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/moz.build
@@ -0,0 +1,53 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+if CONFIG["TARGET_CPU"] == "x86_64":
+ if CONFIG["CC_TYPE"] in ("clang", "gcc"):
+ SOURCES += [
+ "xptcinvoke_x86_64.cpp",
+ "xptcstubs_x86_64_gnu.cpp",
+ ]
+ SOURCES += ["xptcinvoke_asm_x86_64_gnu.s"]
+ else:
+ SOURCES += ["xptcinvoke_x86_64.cpp", "xptcstubs_x86_64.cpp"]
+ SOURCES += ["xptcinvoke_asm_x86_64.asm", "xptcstubs_asm_x86_64.asm"]
+elif CONFIG["TARGET_CPU"] == "x86":
+ if CONFIG["CC_TYPE"] in ("clang", "gcc"):
+ SOURCES += [
+ "xptcinvoke_x86_gnu.cpp",
+ "xptcstubs.cpp",
+ ]
+ else:
+ SOURCES += [
+ "xptcinvoke.cpp",
+ "xptcinvoke_asm_x86_msvc.asm",
+ "xptcstubs.cpp",
+ ]
+ SOURCES["xptcinvoke_asm_x86_msvc.asm"].flags += ["-safeseh"]
+elif CONFIG["TARGET_CPU"] == "aarch64":
+ SOURCES += [
+ "xptcinvoke_aarch64.cpp",
+ "xptcstubs_aarch64.cpp",
+ ]
+ asm_files = [
+ "xptcinvoke_asm_aarch64.asm",
+ "xptcstubs_asm_aarch64.asm",
+ ]
+
+ # make gets confused if the srcdir and objdir files have the same name, so
+ # we generate different names for the objdir files
+ for src in asm_files:
+ obj = src.replace("_asm_aarch64", "")
+ GeneratedFile(
+ obj, script="preprocess.py", entry_point="preprocess", inputs=[src]
+ )
+ SOURCES += ["!%s" % obj]
+
+FINAL_LIBRARY = "xul"
+
+LOCAL_INCLUDES += [
+ "../..",
+]
diff --git a/xpcom/reflect/xptcall/md/win32/preprocess.py b/xpcom/reflect/xptcall/md/win32/preprocess.py
new file mode 100644
index 0000000000..a2f3232c34
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/preprocess.py
@@ -0,0 +1,44 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import errno
+import os
+import shlex
+import subprocess
+import sys
+import tempfile
+
+import buildconfig
+from mozfile import which
+
+
+def preprocess(out, asm_file):
+ cxx = shlex.split(buildconfig.substs["CXX"])
+ if not os.path.exists(cxx[0]):
+ tool = cxx[0]
+ cxx[0] = which(tool)
+ if not cxx[0]:
+ raise OSError(errno.ENOENT, "Could not find {} on PATH.".format(tool))
+
+ cppflags = buildconfig.substs["OS_CPPFLAGS"]
+
+ # subprocess.Popen(stdout=) only accepts actual file objects, which `out`,
+ # above, is not. So fake a temporary file to write to.
+ (outhandle, tmpout) = tempfile.mkstemp(suffix=".cpp")
+
+ # #line directives will confuse armasm64, and /EP is the only way to
+ # preprocess without emitting #line directives.
+ command = cxx + ["/EP"] + cppflags + ["/TP", asm_file]
+ with open(tmpout, "wb") as t:
+ result = subprocess.Popen(command, stdout=t).wait()
+ if result != 0:
+ sys.exit(result)
+
+ with open(tmpout, "rb") as t:
+ out.write(t.read())
+
+ os.close(outhandle)
+ os.remove(tmpout)
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp
new file mode 100644
index 0000000000..e4e63edc4b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#ifndef WIN32
+#error "This code is for Win32 only"
+#endif
+
+extern "C" void __fastcall
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ for(; paramCount > 0; paramCount--, d++, s++)
+ {
+ if(s->IsIndirect())
+ {
+ *((void**)d) = &s->val;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_aarch64.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke_aarch64.cpp
new file mode 100644
index 0000000000..1c1860fbeb
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_aarch64.cpp
@@ -0,0 +1,141 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if !defined(_MSC_VER) && !defined(_M_ARM64)
+#error "This code is for AArch64 Windows only"
+#endif
+
+/* "Procedure Call Standard for the ARM 64-bit Architecture" document, sections
+ * "5.4 Parameter Passing" and "6.1.2 Procedure Calling" contain all the
+ * needed information.
+ *
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf
+ *
+ * Windows follows this document, see:
+ *
+ * https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions
+ */
+
+/*
+ * Allocation of integer function arguments initially to registers r1-r7
+ * and then to stack. Handling of 'that' argument which goes to register r0
+ * is handled separately and does not belong here.
+ *
+ * 'ireg_args' - pointer to the current position in the buffer,
+ * corresponding to the register arguments
+ * 'stack_args' - pointer to the current position in the buffer,
+ * corresponding to the arguments on stack
+ * 'end' - pointer to the end of the registers argument
+ * buffer.
+ */
+static inline void alloc_word(uint64_t* &ireg_args,
+ uint64_t* &stack_args,
+ uint64_t* end,
+ uint64_t data)
+{
+ if (ireg_args < end) {
+ *ireg_args = data;
+ ireg_args++;
+ } else {
+ *stack_args = data;
+ stack_args++;
+ }
+}
+
+static inline void alloc_double(double* &freg_args,
+ uint64_t* &stack_args,
+ double* end,
+ double data)
+{
+ if (freg_args < end) {
+ *freg_args = data;
+ freg_args++;
+ } else {
+ memcpy(stack_args, &data, sizeof(data));
+ stack_args++;
+ }
+}
+
+static inline void alloc_float(double* &freg_args,
+ uint64_t* &stack_args,
+ double* end,
+ float data)
+{
+ if (freg_args < end) {
+ memcpy(freg_args, &data, sizeof(data));
+ freg_args++;
+ } else {
+ memcpy(stack_args, &data, sizeof(data));
+ stack_args++;
+ }
+}
+
+
+extern "C" void
+invoke_copy_to_stack(uint64_t* stk, uint64_t *end,
+ uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint64_t *ireg_args = stk;
+ uint64_t *ireg_end = ireg_args + 8;
+ double *freg_args = (double *)ireg_end;
+ double *freg_end = freg_args + 8;
+ uint64_t *stack_args = (uint64_t *)freg_end;
+
+ // leave room for 'that' argument in x0
+ ++ireg_args;
+
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ uint64_t word;
+
+ if (s->IsIndirect()) {
+ word = (uint64_t)&s->val;
+ } else {
+ // According to the ABI, integral types that are smaller than 8
+ // bytes are to be passed in 8-byte registers or 8-byte stack
+ // slots.
+ switch (s->type) {
+ case nsXPTType::T_FLOAT:
+ alloc_float(freg_args, stack_args, freg_end, s->val.f);
+ continue;
+ case nsXPTType::T_DOUBLE:
+ alloc_double(freg_args, stack_args, freg_end, s->val.d);
+ continue;
+ case nsXPTType::T_I8: word = s->val.i8; break;
+ case nsXPTType::T_I16: word = s->val.i16; break;
+ case nsXPTType::T_I32: word = s->val.i32; break;
+ case nsXPTType::T_I64: word = s->val.i64; break;
+ case nsXPTType::T_U8: word = s->val.u8; break;
+ case nsXPTType::T_U16: word = s->val.u16; break;
+ case nsXPTType::T_U32: word = s->val.u32; break;
+ case nsXPTType::T_U64: word = s->val.u64; break;
+ case nsXPTType::T_BOOL: word = s->val.b; break;
+ case nsXPTType::T_CHAR: word = s->val.c; break;
+ case nsXPTType::T_WCHAR: word = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ word = reinterpret_cast<uint64_t>(s->val.p);
+ break;
+ }
+ }
+
+ alloc_word(ireg_args, stack_args, ireg_end, word);
+ }
+}
+
+extern "C" nsresult
+XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+extern "C"
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ return XPTC__InvokebyIndex(that, methodIndex, paramCount, params);
+}
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_aarch64.asm b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_aarch64.asm
new file mode 100644
index 0000000000..21f80f4cb3
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_aarch64.asm
@@ -0,0 +1,66 @@
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "ksarm64.h"
+
+ IMPORT |invoke_copy_to_stack|
+ TEXTAREA
+
+;
+;XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex,
+; uint32_t paramCount, nsXPTCVariant* params)
+;
+
+ NESTED_ENTRY XPTC__InvokebyIndex
+
+ ; set up frame
+ PROLOG_SAVE_REG_PAIR fp, lr, #-32!
+ PROLOG_SAVE_REG_PAIR x19, x20, #16
+
+ ; save methodIndex across function calls
+ mov w20, w1
+
+ ; end of stack area passed to invoke_copy_to_stack
+ mov x1, sp
+
+ ; assume 8 bytes of stack for each argument with 16-byte alignment
+ add w19, w2, #1
+ and w19, w19, #0xfffffffe
+ sub sp, sp, w19, uxth #3
+
+ ; temporary place to store args passed in r0-r7,v0-v7
+ sub sp, sp, #128
+
+ ; save 'that' on stack
+ str x0, [sp]
+
+ ; start of stack area passed to invoke_copy_to_stack
+ mov x0, sp
+ bl invoke_copy_to_stack
+
+ ; load arguments passed in r0-r7
+ ldp x6, x7, [sp, #48]
+ ldp x4, x5, [sp, #32]
+ ldp x2, x3, [sp, #16]
+ ldp x0, x1, [sp],#64
+
+ ; load arguments passed in v0-v7
+ ldp d6, d7, [sp, #48]
+ ldp d4, d5, [sp, #32]
+ ldp d2, d3, [sp, #16]
+ ldp d0, d1, [sp],#64
+
+ ; call the method
+ ldr x16, [x0]
+ add x16, x16, w20, uxth #3
+ ldr x16, [x16]
+ blr x16
+
+ EPILOG_STACK_RESTORE
+ EPILOG_RESTORE_REG_PAIR x19, x20, #16
+ EPILOG_RESTORE_REG_PAIR x29, x30, #32!
+ EPILOG_RETURN
+
+ NESTED_END XPTC__InvokebyIndex
+ END
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm
new file mode 100644
index 0000000000..bf7c2ef0c3
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm
@@ -0,0 +1,107 @@
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+extrn invoke_copy_to_stack:PROC
+
+
+.CODE
+
+;
+;XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex,
+; uint32_t paramCount, nsXPTCVariant* params)
+;
+
+XPTC__InvokebyIndex PROC FRAME
+
+ ; store register parameters
+
+ mov qword ptr [rsp+32], r9 ; params
+ mov dword ptr [rsp+24], r8d ; paramCount
+ mov dword ptr [rsp+16], edx ; methodIndex
+ mov qword ptr [rsp+8], rcx ; that
+
+ push rbp
+ .PUSHREG rbp
+ mov rbp, rsp ; store current RSP to RBP
+ .SETFRAME rbp, 0
+ .ENDPROLOG
+
+ sub rsp, 32
+
+ ; maybe we don't have any parameters to copy
+
+ test r8d, r8d
+ jz noparams
+
+ ;
+ ; Build stack for stdcall
+ ;
+
+ ; 1st parameter is space for parameters
+
+ mov eax, r8d
+ or eax, 1
+ shl rax, 3 ; *= 8
+ sub rsp, rax
+ mov rcx, rsp
+
+ ; 2nd parameter is parameter count
+
+ mov edx, r8d
+
+ ; 3rd parameter is params
+
+ mov r8, r9
+
+ sub rsp, 40
+ call invoke_copy_to_stack ; rcx = d
+ ; edx = paramCount
+ ; r8 = s
+ add rsp, 32
+
+ ; Current stack is the following.
+ ;
+ ; 0h: [space (for this)]
+ ; 8h: [1st parameter]
+ ; 10h: [2nd parameter]
+ ; 18h: [3rd parameter]
+ ; 20h: [4th parameter]
+ ; ...
+ ;
+ ; On Win64 ABI, the first 4 parameters are passed using registers,
+ ; and others are on stack.
+
+ ; 1st, 2nd and 3rd arguments are passed via registers
+
+ mov rdx, qword ptr [rsp+8] ; 1st parameter
+ movsd xmm1, qword ptr [rsp+8] ; for double
+
+ mov r8, qword ptr [rsp+16] ; 2nd parameter
+ movsd xmm2, qword ptr [rsp+16] ; for double
+
+ mov r9, qword ptr [rsp+24] ; 3rd parameter
+ movsd xmm3, qword ptr [rsp+24] ; for double
+
+ ; rcx register is this
+
+ mov rcx, qword ptr [rbp+8+8] ; that
+
+noparams:
+
+ ; calculate call address
+
+ mov r11, qword ptr [rcx]
+ mov eax, dword ptr [rbp+16+8] ; methodIndex
+
+ call qword ptr [r11+rax*8] ; stdcall, i.e. callee cleans up stack.
+
+ mov rsp, rbp
+ pop rbp
+
+ ret
+
+XPTC__InvokebyIndex ENDP
+
+
+END
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s
new file mode 100644
index 0000000000..5cc19b4c57
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s
@@ -0,0 +1,110 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+.extern invoke_copy_to_stack
+
+
+.text
+.intel_syntax noprefix
+
+#
+#_XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+.globl XPTC__InvokebyIndex
+.def XPTC__InvokebyIndex
+ .scl 2
+ .type 46
+.endef
+XPTC__InvokebyIndex:
+
+ # store register parameters
+
+ mov qword ptr [rsp+32], r9 # params
+ mov dword ptr [rsp+24], r8d # paramCount
+ mov dword ptr [rsp+16], edx # methodIndex
+ mov qword ptr [rsp+8], rcx # that
+
+ push rbp
+ # .PUSHREG rbp
+ mov rbp, rsp # store current RSP to RBP
+ # .SETFRAME rbp, 0
+ # .ENDPROLOG
+
+ sub rsp, 32
+
+ # maybe we don't have any parameters to copy
+
+ test r8d, r8d
+ jz noparams
+
+ #
+ # Build stack for stdcall
+ #
+
+ # 1st parameter is space for parameters
+
+ mov eax, r8d
+ or eax, 1
+ shl rax, 3 # *= 8
+ sub rsp, rax
+ mov rcx, rsp
+
+ # 2nd parameter is parameter count
+
+ mov edx, r8d
+
+ # 3rd parameter is params
+
+ mov r8, r9
+
+ sub rsp, 40
+ call invoke_copy_to_stack # rcx = d
+ # edx = paramCount
+ # r8 = s
+ add rsp, 32
+
+ # Current stack is the following.
+ #
+ # 0h: [space (for this)]
+ # 8h: [1st parameter]
+ # 10h: [2nd parameter]
+ # 18h: [3rd parameter]
+ # 20h: [4th parameter]
+ # ...
+ #
+ # On Win64 ABI, the first 4 parameters are passed using registers,
+ # and others are on stack.
+
+ # 1st, 2nd and 3rd arguments are passed via registers
+
+ mov rdx, qword ptr [rsp+8] # 1st parameter
+ movsd xmm1, qword ptr [rsp+8] # for double
+
+ mov r8, qword ptr [rsp+16] # 2nd parameter
+ movsd xmm2, qword ptr [rsp+16] # for double
+
+ mov r9, qword ptr [rsp+24] # 3rd parameter
+ movsd xmm3, qword ptr [rsp+24] # for double
+
+ # rcx register is this
+
+ mov rcx, qword ptr [rbp+8+8] # that
+
+noparams:
+
+ # calculate call address
+
+ mov r11, qword ptr [rcx]
+ mov eax, dword ptr [rbp+16+8] # methodIndex
+
+ call qword ptr [r11+rax*8] # stdcall, i.e. callee cleans up stack.
+
+ mov rsp, rbp
+ pop rbp
+
+ ret
+
+
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm
new file mode 100644
index 0000000000..f3b7a1826d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm
@@ -0,0 +1,63 @@
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ TITLE xptcinvoke_asm_x86_msvc.asm
+ .686P
+ .model flat
+
+PUBLIC _NS_InvokeByIndex
+EXTRN @invoke_copy_to_stack@12:PROC
+
+;
+; extern "C" nsresult __cdecl
+; NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+; uint32_t paramCount, nsXPTCVariant* params)
+;
+
+_TEXT SEGMENT
+_NS_InvokeByIndex PROC
+
+ ; Build frame
+ push ebp
+ mov ebp, esp
+
+ ; Save paramCount for later
+ mov edx, dword ptr [ebp+16]
+
+ ; Do we have any parameters?
+ test edx, edx
+ jz noparams
+
+ ; Build call for copy_to_stack, which is __fastcall
+
+ ; Allocate space for parameters. 8 is the biggest size
+ ; any parameter can be, so assume that all our parameters
+ ; are that large.
+ mov eax, edx
+ shl eax, 3
+ sub esp, eax
+
+ mov ecx, esp
+ push dword ptr [ebp+20]
+ call @invoke_copy_to_stack@12
+noparams:
+ ; Push the `this' parameter for the call.
+ mov ecx, dword ptr [ebp+8]
+ push ecx
+
+ ; Load the vtable.
+ mov edx, dword ptr [ecx]
+
+ ; Call the vtable index at `methodIndex'.
+ mov eax, dword ptr [ebp+12]
+ call dword ptr [edx+eax*4]
+
+ ; Reset and return.
+ mov esp, ebp
+ pop ebp
+ ret
+_NS_InvokeByIndex ENDP
+_TEXT ENDS
+
+END
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp
new file mode 100644
index 0000000000..47c891acea
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+extern "C" void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ for(; paramCount > 0; paramCount--, d++, s++)
+ {
+ if(s->IsIndirect())
+ {
+ *((void**)d) = &s->val;
+ continue;
+ }
+
+ /*
+ * AMD64 platform uses 8 bytes align.
+ */
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; break;
+ case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; break;
+ case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" nsresult
+XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+extern "C"
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ return XPTC__InvokebyIndex(that, methodIndex, paramCount, params);
+}
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp
new file mode 100644
index 0000000000..7576919b5a
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp
@@ -0,0 +1,106 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+extern "C" {
+void __attribute__ ((__used__)) __attribute__ ((regparm(3)))
+invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d)
+{
+ for(uint32_t i = paramCount; i >0; i--, d++, s++)
+ {
+ if(s->IsIndirect())
+ {
+ *((void**)d) = &s->val;
+ continue;
+ }
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+} // extern "C"
+
+/*
+ EXPORT_XPCOM_API(nsresult)
+ NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+ Each param takes at most two 4-byte words.
+ It doesn't matter if we push too many words, and calculating the exact
+ amount takes time.
+
+ that = ebp + 0x08
+ methodIndex = ebp + 0x0c
+ paramCount = ebp + 0x10
+ params = ebp + 0x14
+
+*/
+
+__asm__ (
+ ".text\n\t"
+/* alignment here seems unimportant here; this was 16, now it's 2 which
+ is what xptcstubs uses. */
+ ".align 2\n\t"
+ ".globl _NS_InvokeByIndex\n\t"
+ "_NS_InvokeByIndex:\n\t"
+ "pushl %ebp\n\t"
+ "movl %esp, %ebp\n\t"
+ "movl 0x10(%ebp), %eax\n\t"
+ "leal 0(,%eax,8),%edx\n\t"
+
+ /* set up call frame for method. */
+ "subl %edx, %esp\n\t" /* make room for params. */
+/* Align to maximum x86 data size: 128 bits == 16 bytes == XMM register size.
+ * This is to avoid protection faults where SSE+ alignment of stack pointer
+ * is assumed and required, e.g. by GCC4's -ftree-vectorize option.
+ */
+ "andl $0xfffffff0, %esp\n\t" /* drop(?) stack ptr to 128-bit align */
+/* $esp should be aligned to a 16-byte boundary here (note we include an
+ * additional 4 bytes in a later push instruction). This will ensure $ebp
+ * in the function called below is aligned to a 0x8 boundary. SSE instructions
+ * like movapd/movdqa expect memory operand to be aligned on a 16-byte
+ * boundary. The GCC compiler will generate the memory operand using $ebp
+ * with an 8-byte offset.
+ */
+ "subl $0xc, %esp\n\t" /* lower again; push/call below will re-align */
+ "movl %esp, %ecx\n\t" /* ecx = d */
+ "movl 8(%ebp), %edx\n\t" /* edx = this */
+ "pushl %edx\n\t" /* push this. esp % 16 == 0 */
+
+ "movl 0x14(%ebp), %edx\n\t"
+ "call _invoke_copy_to_stack\n\t"
+ "movl 0x08(%ebp), %ecx\n\t" /* 'that' */
+ "movl (%ecx), %edx\n\t"
+ "movl 0x0c(%ebp), %eax\n\t" /* function index */
+ "leal (%edx,%eax,4), %edx\n\t"
+ "call *(%edx)\n\t"
+ "movl %ebp, %esp\n\t"
+ "popl %ebp\n\t"
+ "ret\n"
+ ".section .drectve\n\t"
+ ".ascii \" -export:NS_InvokeByIndex\"\n\t"
+ ".text\n\t"
+);
diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp
new file mode 100644
index 0000000000..d669aafddf
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp
@@ -0,0 +1,133 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#ifndef WIN32
+#error "This code is for Win32 only"
+#endif
+
+extern "C" {
+
+static
+nsresult __stdcall
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint32_t* args, uint32_t* stackBytesToPop)
+{
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+
+ // If anything fails before stackBytesToPop can be set then
+ // the failure is completely catastrophic!
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext)
+ ap++;
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+ *stackBytesToPop = ((uint32_t)ap) - ((uint32_t)args);
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+} // extern "C"
+
+static MOZ_NAKED void SharedStub(void)
+{
+ __asm {
+ push ebp // set up simple stack frame
+ mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args
+ push ecx // make room for a ptr
+ lea eax, [ebp-4] // pointer to stackBytesToPop
+ push eax
+ lea eax, [ebp+12] // pointer to args
+ push eax
+ push ecx // vtbl_index
+ mov eax, [ebp+8] // this
+ push eax
+ call PrepareAndDispatch
+ mov edx, [ebp+4] // return address
+ mov ecx, [ebp-4] // stackBytesToPop
+ add ecx, 8 // for 'this' and return address
+ mov esp, ebp
+ pop ebp
+ add esp, ecx // fix up stack pointer
+ jmp edx // simulate __stdcall return
+ }
+}
+
+// these macros get expanded (many times) in the file #included below
+#define STUB_ENTRY(n) \
+MOZ_NAKED nsresult __stdcall nsXPTCStubBase::Stub##n() \
+{ __asm mov ecx, n __asm jmp SharedStub }
+
+#define SENTINEL_ENTRY(n) \
+nsresult __stdcall nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4035) // OK to have no return value
+#endif
+#include "xptcstubsdef.inc"
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+void
+xptc_dummy()
+{
+}
diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_aarch64.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs_aarch64.cpp
new file mode 100644
index 0000000000..57d78c5a7a
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_aarch64.cpp
@@ -0,0 +1,186 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+/*
+ * This is for AArch64 ABI
+ *
+ * When we're called, the "gp" registers are stored in gprData and
+ * the "fp" registers are stored in fprData. Each array has 8 regs
+ * but first reg in gprData is a placeholder for 'self'.
+ */
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args,
+ uint64_t *gprData, double *fprData)
+{
+#define PARAM_GPR_COUNT 8
+#define PARAM_FPR_COUNT 8
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ uint32_t paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint64_t* ap = args;
+ uint32_t next_gpr = 1; // skip first arg which is 'self'
+ uint32_t next_fpr = 0;
+ for (uint32_t i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (next_gpr < PARAM_GPR_COUNT)
+ next_gpr++;
+ else
+ ap++;
+ }
+
+ if (param.IsOut() || !type.IsArithmetic()) {
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.p = (void*)gprData[next_gpr++];
+ } else {
+ dp->val.p = (void*)*ap++;
+ }
+ continue;
+ }
+
+ switch (type) {
+ case nsXPTType::T_I8:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.i8 = (int8_t)gprData[next_gpr++];
+ } else {
+ dp->val.i8 = (int8_t)*ap++;
+ }
+ break;
+
+ case nsXPTType::T_I16:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.i16 = (int16_t)gprData[next_gpr++];
+ } else {
+ dp->val.i16 = (int16_t)*ap++;
+ }
+ break;
+
+ case nsXPTType::T_I32:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.i32 = (int32_t)gprData[next_gpr++];
+ } else {
+ dp->val.i32 = (int32_t)*ap++;
+ }
+ break;
+
+ case nsXPTType::T_I64:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.i64 = (int64_t)gprData[next_gpr++];
+ } else {
+ dp->val.i64 = (int64_t)*ap++;
+ }
+ break;
+
+ case nsXPTType::T_U8:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.u8 = (uint8_t)gprData[next_gpr++];
+ } else {
+ dp->val.u8 = (uint8_t)*ap++;
+ }
+ break;
+
+ case nsXPTType::T_U16:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.u16 = (uint16_t)gprData[next_gpr++];
+ } else {
+ dp->val.u16 = (uint16_t)*ap++;
+ }
+ break;
+
+ case nsXPTType::T_U32:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.u32 = (uint32_t)gprData[next_gpr++];
+ } else {
+ dp->val.u32 = (uint32_t)*ap++;
+ }
+ break;
+
+ case nsXPTType::T_U64:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.u64 = (uint64_t)gprData[next_gpr++];
+ } else {
+ dp->val.u64 = (uint64_t)*ap++;
+ }
+ break;
+
+ case nsXPTType::T_FLOAT:
+ if (next_fpr < PARAM_FPR_COUNT) {
+ memcpy(&dp->val.f, &fprData[next_fpr++], sizeof(dp->val.f));
+ } else {
+ memcpy(&dp->val.f, ap++, sizeof(dp->val.f));
+ }
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ if (next_fpr < PARAM_FPR_COUNT) {
+ memcpy(&dp->val.d, &fprData[next_fpr++], sizeof(dp->val.d));
+ } else {
+ memcpy(&dp->val.d, ap++, sizeof(dp->val.d));
+ }
+ break;
+
+ case nsXPTType::T_BOOL:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.b = (bool)(uint8_t)gprData[next_gpr++];
+ } else {
+ dp->val.b = (bool)(uint8_t)*ap++;
+ }
+ break;
+
+ case nsXPTType::T_CHAR:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.c = (char)gprData[next_gpr++];
+ } else {
+ dp->val.c = (char)*ap++;
+ }
+ break;
+
+ case nsXPTType::T_WCHAR:
+ if (next_gpr < PARAM_GPR_COUNT) {
+ dp->val.wc = (wchar_t)gprData[next_gpr++];
+ } else {
+ dp->val.wc = (wchar_t)*ap++;
+ }
+ break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+#define STUB_ENTRY(n) /* defined in the assembly file */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_aarch64.asm b/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_aarch64.asm
new file mode 100644
index 0000000000..28b3d8866f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_aarch64.asm
@@ -0,0 +1,306 @@
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "ksarm64.h"
+
+NGPREGS EQU 8
+NFPREGS EQU 8
+
+ IMPORT |PrepareAndDispatch|
+
+ TEXTAREA
+
+ NESTED_ENTRY SharedStub
+
+ PROLOG_SAVE_REG_PAIR x29, x30, #-16!
+
+ sub sp, sp, #128 ; 8*(NGPREGS+NFPREGS)
+ stp x0, x1, [sp, #64+(0*8)]
+ stp x2, x3, [sp, #64+(2*8)]
+ stp x4, x5, [sp, #64+(4*8)]
+ stp x6, x7, [sp, #64+(6*8)]
+ stp d0, d1, [sp, #(0*8)]
+ stp d2, d3, [sp, #(2*8)]
+ stp d4, d5, [sp, #(4*8)]
+ stp d6, d7, [sp, #(6*8)]
+
+ ; methodIndex passed from stub
+ mov w1, w17
+
+ add x2, sp, #144 ; 16+(8*(NGPREGS+NFPREGS))
+ add x3, sp, #64 ; 8*NFPREGS
+ add x4, sp, #0
+
+ bl PrepareAndDispatch
+
+ EPILOG_STACK_RESTORE
+ EPILOG_RESTORE_REG_PAIR x29, x30, #16!
+ EPILOG_RETURN
+
+ NESTED_END SharedStub
+
+
+ MACRO
+ STUBENTRY $functionname, $paramcount
+ EXPORT |$functionname|
+ TEXTAREA
+
+ LEAF_ENTRY |$functionname|
+
+ mov w17, $paramcount
+ b SharedStub
+
+ LEAF_END |$functionname|
+
+ MEND
+
+ STUBENTRY ?Stub3@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 3
+ STUBENTRY ?Stub4@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 4
+ STUBENTRY ?Stub5@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 5
+ STUBENTRY ?Stub6@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 6
+ STUBENTRY ?Stub7@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 7
+ STUBENTRY ?Stub8@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 8
+ STUBENTRY ?Stub9@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 9
+ STUBENTRY ?Stub10@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 10
+ STUBENTRY ?Stub11@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 11
+ STUBENTRY ?Stub12@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 12
+ STUBENTRY ?Stub13@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 13
+ STUBENTRY ?Stub14@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 14
+ STUBENTRY ?Stub15@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 15
+ STUBENTRY ?Stub16@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 16
+ STUBENTRY ?Stub17@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 17
+ STUBENTRY ?Stub18@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 18
+ STUBENTRY ?Stub19@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 19
+ STUBENTRY ?Stub20@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 20
+ STUBENTRY ?Stub21@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 21
+ STUBENTRY ?Stub22@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 22
+ STUBENTRY ?Stub23@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 23
+ STUBENTRY ?Stub24@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 24
+ STUBENTRY ?Stub25@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 25
+ STUBENTRY ?Stub26@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 26
+ STUBENTRY ?Stub27@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 27
+ STUBENTRY ?Stub28@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 28
+ STUBENTRY ?Stub29@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 29
+ STUBENTRY ?Stub30@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 30
+ STUBENTRY ?Stub31@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 31
+ STUBENTRY ?Stub32@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 32
+ STUBENTRY ?Stub33@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 33
+ STUBENTRY ?Stub34@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 34
+ STUBENTRY ?Stub35@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 35
+ STUBENTRY ?Stub36@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 36
+ STUBENTRY ?Stub37@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 37
+ STUBENTRY ?Stub38@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 38
+ STUBENTRY ?Stub39@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 39
+ STUBENTRY ?Stub40@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 40
+ STUBENTRY ?Stub41@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 41
+ STUBENTRY ?Stub42@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 42
+ STUBENTRY ?Stub43@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 43
+ STUBENTRY ?Stub44@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 44
+ STUBENTRY ?Stub45@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 45
+ STUBENTRY ?Stub46@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 46
+ STUBENTRY ?Stub47@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 47
+ STUBENTRY ?Stub48@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 48
+ STUBENTRY ?Stub49@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 49
+ STUBENTRY ?Stub50@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 50
+ STUBENTRY ?Stub51@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 51
+ STUBENTRY ?Stub52@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 52
+ STUBENTRY ?Stub53@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 53
+ STUBENTRY ?Stub54@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 54
+ STUBENTRY ?Stub55@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 55
+ STUBENTRY ?Stub56@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 56
+ STUBENTRY ?Stub57@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 57
+ STUBENTRY ?Stub58@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 58
+ STUBENTRY ?Stub59@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 59
+ STUBENTRY ?Stub60@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 60
+ STUBENTRY ?Stub61@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 61
+ STUBENTRY ?Stub62@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 62
+ STUBENTRY ?Stub63@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 63
+ STUBENTRY ?Stub64@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 64
+ STUBENTRY ?Stub65@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 65
+ STUBENTRY ?Stub66@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 66
+ STUBENTRY ?Stub67@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 67
+ STUBENTRY ?Stub68@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 68
+ STUBENTRY ?Stub69@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 69
+ STUBENTRY ?Stub70@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 70
+ STUBENTRY ?Stub71@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 71
+ STUBENTRY ?Stub72@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 72
+ STUBENTRY ?Stub73@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 73
+ STUBENTRY ?Stub74@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 74
+ STUBENTRY ?Stub75@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 75
+ STUBENTRY ?Stub76@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 76
+ STUBENTRY ?Stub77@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 77
+ STUBENTRY ?Stub78@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 78
+ STUBENTRY ?Stub79@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 79
+ STUBENTRY ?Stub80@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 80
+ STUBENTRY ?Stub81@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 81
+ STUBENTRY ?Stub82@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 82
+ STUBENTRY ?Stub83@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 83
+ STUBENTRY ?Stub84@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 84
+ STUBENTRY ?Stub85@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 85
+ STUBENTRY ?Stub86@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 86
+ STUBENTRY ?Stub87@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 87
+ STUBENTRY ?Stub88@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 88
+ STUBENTRY ?Stub89@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 89
+ STUBENTRY ?Stub90@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 90
+ STUBENTRY ?Stub91@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 91
+ STUBENTRY ?Stub92@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 92
+ STUBENTRY ?Stub93@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 93
+ STUBENTRY ?Stub94@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 94
+ STUBENTRY ?Stub95@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 95
+ STUBENTRY ?Stub96@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 96
+ STUBENTRY ?Stub97@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 97
+ STUBENTRY ?Stub98@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 98
+ STUBENTRY ?Stub99@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 99
+ STUBENTRY ?Stub100@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 100
+ STUBENTRY ?Stub101@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 101
+ STUBENTRY ?Stub102@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 102
+ STUBENTRY ?Stub103@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 103
+ STUBENTRY ?Stub104@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 104
+ STUBENTRY ?Stub105@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 105
+ STUBENTRY ?Stub106@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 106
+ STUBENTRY ?Stub107@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 107
+ STUBENTRY ?Stub108@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 108
+ STUBENTRY ?Stub109@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 109
+ STUBENTRY ?Stub110@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 110
+ STUBENTRY ?Stub111@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 111
+ STUBENTRY ?Stub112@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 112
+ STUBENTRY ?Stub113@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 113
+ STUBENTRY ?Stub114@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 114
+ STUBENTRY ?Stub115@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 115
+ STUBENTRY ?Stub116@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 116
+ STUBENTRY ?Stub117@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 117
+ STUBENTRY ?Stub118@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 118
+ STUBENTRY ?Stub119@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 119
+ STUBENTRY ?Stub120@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 120
+ STUBENTRY ?Stub121@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 121
+ STUBENTRY ?Stub122@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 122
+ STUBENTRY ?Stub123@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 123
+ STUBENTRY ?Stub124@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 124
+ STUBENTRY ?Stub125@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 125
+ STUBENTRY ?Stub126@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 126
+ STUBENTRY ?Stub127@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 127
+ STUBENTRY ?Stub128@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 128
+ STUBENTRY ?Stub129@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 129
+ STUBENTRY ?Stub130@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 130
+ STUBENTRY ?Stub131@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 131
+ STUBENTRY ?Stub132@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 132
+ STUBENTRY ?Stub133@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 133
+ STUBENTRY ?Stub134@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 134
+ STUBENTRY ?Stub135@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 135
+ STUBENTRY ?Stub136@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 136
+ STUBENTRY ?Stub137@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 137
+ STUBENTRY ?Stub138@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 138
+ STUBENTRY ?Stub139@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 139
+ STUBENTRY ?Stub140@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 140
+ STUBENTRY ?Stub141@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 141
+ STUBENTRY ?Stub142@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 142
+ STUBENTRY ?Stub143@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 143
+ STUBENTRY ?Stub144@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 144
+ STUBENTRY ?Stub145@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 145
+ STUBENTRY ?Stub146@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 146
+ STUBENTRY ?Stub147@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 147
+ STUBENTRY ?Stub148@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 148
+ STUBENTRY ?Stub149@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 149
+ STUBENTRY ?Stub150@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 150
+ STUBENTRY ?Stub151@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 151
+ STUBENTRY ?Stub152@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 152
+ STUBENTRY ?Stub153@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 153
+ STUBENTRY ?Stub154@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 154
+ STUBENTRY ?Stub155@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 155
+ STUBENTRY ?Stub156@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 156
+ STUBENTRY ?Stub157@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 157
+ STUBENTRY ?Stub158@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 158
+ STUBENTRY ?Stub159@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 159
+ STUBENTRY ?Stub160@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 160
+ STUBENTRY ?Stub161@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 161
+ STUBENTRY ?Stub162@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 162
+ STUBENTRY ?Stub163@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 163
+ STUBENTRY ?Stub164@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 164
+ STUBENTRY ?Stub165@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 165
+ STUBENTRY ?Stub166@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 166
+ STUBENTRY ?Stub167@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 167
+ STUBENTRY ?Stub168@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 168
+ STUBENTRY ?Stub169@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 169
+ STUBENTRY ?Stub170@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 170
+ STUBENTRY ?Stub171@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 171
+ STUBENTRY ?Stub172@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 172
+ STUBENTRY ?Stub173@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 173
+ STUBENTRY ?Stub174@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 174
+ STUBENTRY ?Stub175@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 175
+ STUBENTRY ?Stub176@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 176
+ STUBENTRY ?Stub177@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 177
+ STUBENTRY ?Stub178@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 178
+ STUBENTRY ?Stub179@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 179
+ STUBENTRY ?Stub180@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 180
+ STUBENTRY ?Stub181@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 181
+ STUBENTRY ?Stub182@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 182
+ STUBENTRY ?Stub183@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 183
+ STUBENTRY ?Stub184@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 184
+ STUBENTRY ?Stub185@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 185
+ STUBENTRY ?Stub186@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 186
+ STUBENTRY ?Stub187@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 187
+ STUBENTRY ?Stub188@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 188
+ STUBENTRY ?Stub189@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 189
+ STUBENTRY ?Stub190@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 190
+ STUBENTRY ?Stub191@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 191
+ STUBENTRY ?Stub192@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 192
+ STUBENTRY ?Stub193@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 193
+ STUBENTRY ?Stub194@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 194
+ STUBENTRY ?Stub195@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 195
+ STUBENTRY ?Stub196@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 196
+ STUBENTRY ?Stub197@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 197
+ STUBENTRY ?Stub198@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 198
+ STUBENTRY ?Stub199@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 199
+ STUBENTRY ?Stub200@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 200
+ STUBENTRY ?Stub201@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 201
+ STUBENTRY ?Stub202@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 202
+ STUBENTRY ?Stub203@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 203
+ STUBENTRY ?Stub204@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 204
+ STUBENTRY ?Stub205@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 205
+ STUBENTRY ?Stub206@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 206
+ STUBENTRY ?Stub207@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 207
+ STUBENTRY ?Stub208@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 208
+ STUBENTRY ?Stub209@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 209
+ STUBENTRY ?Stub210@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 210
+ STUBENTRY ?Stub211@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 211
+ STUBENTRY ?Stub212@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 212
+ STUBENTRY ?Stub213@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 213
+ STUBENTRY ?Stub214@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 214
+ STUBENTRY ?Stub215@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 215
+ STUBENTRY ?Stub216@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 216
+ STUBENTRY ?Stub217@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 217
+ STUBENTRY ?Stub218@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 218
+ STUBENTRY ?Stub219@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 219
+ STUBENTRY ?Stub220@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 220
+ STUBENTRY ?Stub221@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 221
+ STUBENTRY ?Stub222@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 222
+ STUBENTRY ?Stub223@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 223
+ STUBENTRY ?Stub224@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 224
+ STUBENTRY ?Stub225@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 225
+ STUBENTRY ?Stub226@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 226
+ STUBENTRY ?Stub227@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 227
+ STUBENTRY ?Stub228@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 228
+ STUBENTRY ?Stub229@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 229
+ STUBENTRY ?Stub230@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 230
+ STUBENTRY ?Stub231@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 231
+ STUBENTRY ?Stub232@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 232
+ STUBENTRY ?Stub233@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 233
+ STUBENTRY ?Stub234@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 234
+ STUBENTRY ?Stub235@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 235
+ STUBENTRY ?Stub236@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 236
+ STUBENTRY ?Stub237@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 237
+ STUBENTRY ?Stub238@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 238
+ STUBENTRY ?Stub239@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 239
+ STUBENTRY ?Stub240@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 240
+ STUBENTRY ?Stub241@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 241
+ STUBENTRY ?Stub242@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 242
+ STUBENTRY ?Stub243@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 243
+ STUBENTRY ?Stub244@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 244
+ STUBENTRY ?Stub245@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 245
+ STUBENTRY ?Stub246@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 246
+ STUBENTRY ?Stub247@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 247
+ STUBENTRY ?Stub248@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 248
+ STUBENTRY ?Stub249@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 249
+
+ END
diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm b/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm
new file mode 100644
index 0000000000..db2cc16bee
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm
@@ -0,0 +1,335 @@
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+extrn PrepareAndDispatch:PROC
+
+.code
+
+SharedStub PROC FRAME
+ sub rsp, 104
+ .ALLOCSTACK 104
+ .ENDPROLOG
+
+ ; rcx is this pointer. Need backup for optimized build
+
+ mov qword ptr [rsp+88], rcx
+
+ ;
+ ; fist 4 parameters (1st is "this" pointer) are passed in registers.
+ ;
+
+ ; for floating value
+
+ movsd qword ptr [rsp+64], xmm1
+ movsd qword ptr [rsp+72], xmm2
+ movsd qword ptr [rsp+80], xmm3
+
+ ; for integer value
+
+ mov qword ptr [rsp+40], rdx
+ mov qword ptr [rsp+48], r8
+ mov qword ptr [rsp+56], r9
+
+ ;
+ ; Call PrepareAndDispatch function
+ ;
+
+ ; 5th parameter (floating parameters) of PrepareAndDispatch
+
+ lea r9, qword ptr [rsp+64]
+ mov qword ptr [rsp+32], r9
+
+ ; 4th parameter (normal parameters) of PrepareAndDispatch
+
+ lea r9, qword ptr [rsp+40]
+
+ ; 3rd parameter (pointer to args on stack)
+
+ lea r8, qword ptr [rsp+40+104]
+
+ ; 2nd parameter (vtbl_index)
+
+ mov rdx, r11
+
+ ; 1st parameter (this) (rcx)
+
+ call PrepareAndDispatch
+
+ ; restore rcx
+
+ mov rcx, qword ptr [rsp+88]
+
+ ;
+ ; clean up register
+ ;
+
+ add rsp, 104+8
+
+ ; set return address
+
+ mov rdx, qword ptr [rsp-8]
+
+ ; simulate __stdcall return
+
+ jmp rdx
+
+SharedStub ENDP
+
+
+STUBENTRY MACRO functionname, paramcount
+functionname PROC
+ mov r11, paramcount
+ jmp SharedStub
+functionname ENDP
+ENDM
+
+ STUBENTRY ?Stub3@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 3
+ STUBENTRY ?Stub4@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 4
+ STUBENTRY ?Stub5@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 5
+ STUBENTRY ?Stub6@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 6
+ STUBENTRY ?Stub7@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 7
+ STUBENTRY ?Stub8@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 8
+ STUBENTRY ?Stub9@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 9
+ STUBENTRY ?Stub10@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 10
+ STUBENTRY ?Stub11@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 11
+ STUBENTRY ?Stub12@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 12
+ STUBENTRY ?Stub13@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 13
+ STUBENTRY ?Stub14@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 14
+ STUBENTRY ?Stub15@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 15
+ STUBENTRY ?Stub16@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 16
+ STUBENTRY ?Stub17@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 17
+ STUBENTRY ?Stub18@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 18
+ STUBENTRY ?Stub19@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 19
+ STUBENTRY ?Stub20@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 20
+ STUBENTRY ?Stub21@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 21
+ STUBENTRY ?Stub22@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 22
+ STUBENTRY ?Stub23@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 23
+ STUBENTRY ?Stub24@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 24
+ STUBENTRY ?Stub25@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 25
+ STUBENTRY ?Stub26@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 26
+ STUBENTRY ?Stub27@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 27
+ STUBENTRY ?Stub28@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 28
+ STUBENTRY ?Stub29@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 29
+ STUBENTRY ?Stub30@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 30
+ STUBENTRY ?Stub31@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 31
+ STUBENTRY ?Stub32@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 32
+ STUBENTRY ?Stub33@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 33
+ STUBENTRY ?Stub34@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 34
+ STUBENTRY ?Stub35@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 35
+ STUBENTRY ?Stub36@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 36
+ STUBENTRY ?Stub37@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 37
+ STUBENTRY ?Stub38@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 38
+ STUBENTRY ?Stub39@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 39
+ STUBENTRY ?Stub40@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 40
+ STUBENTRY ?Stub41@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 41
+ STUBENTRY ?Stub42@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 42
+ STUBENTRY ?Stub43@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 43
+ STUBENTRY ?Stub44@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 44
+ STUBENTRY ?Stub45@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 45
+ STUBENTRY ?Stub46@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 46
+ STUBENTRY ?Stub47@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 47
+ STUBENTRY ?Stub48@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 48
+ STUBENTRY ?Stub49@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 49
+ STUBENTRY ?Stub50@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 50
+ STUBENTRY ?Stub51@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 51
+ STUBENTRY ?Stub52@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 52
+ STUBENTRY ?Stub53@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 53
+ STUBENTRY ?Stub54@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 54
+ STUBENTRY ?Stub55@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 55
+ STUBENTRY ?Stub56@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 56
+ STUBENTRY ?Stub57@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 57
+ STUBENTRY ?Stub58@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 58
+ STUBENTRY ?Stub59@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 59
+ STUBENTRY ?Stub60@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 60
+ STUBENTRY ?Stub61@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 61
+ STUBENTRY ?Stub62@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 62
+ STUBENTRY ?Stub63@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 63
+ STUBENTRY ?Stub64@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 64
+ STUBENTRY ?Stub65@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 65
+ STUBENTRY ?Stub66@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 66
+ STUBENTRY ?Stub67@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 67
+ STUBENTRY ?Stub68@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 68
+ STUBENTRY ?Stub69@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 69
+ STUBENTRY ?Stub70@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 70
+ STUBENTRY ?Stub71@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 71
+ STUBENTRY ?Stub72@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 72
+ STUBENTRY ?Stub73@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 73
+ STUBENTRY ?Stub74@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 74
+ STUBENTRY ?Stub75@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 75
+ STUBENTRY ?Stub76@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 76
+ STUBENTRY ?Stub77@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 77
+ STUBENTRY ?Stub78@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 78
+ STUBENTRY ?Stub79@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 79
+ STUBENTRY ?Stub80@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 80
+ STUBENTRY ?Stub81@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 81
+ STUBENTRY ?Stub82@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 82
+ STUBENTRY ?Stub83@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 83
+ STUBENTRY ?Stub84@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 84
+ STUBENTRY ?Stub85@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 85
+ STUBENTRY ?Stub86@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 86
+ STUBENTRY ?Stub87@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 87
+ STUBENTRY ?Stub88@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 88
+ STUBENTRY ?Stub89@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 89
+ STUBENTRY ?Stub90@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 90
+ STUBENTRY ?Stub91@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 91
+ STUBENTRY ?Stub92@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 92
+ STUBENTRY ?Stub93@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 93
+ STUBENTRY ?Stub94@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 94
+ STUBENTRY ?Stub95@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 95
+ STUBENTRY ?Stub96@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 96
+ STUBENTRY ?Stub97@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 97
+ STUBENTRY ?Stub98@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 98
+ STUBENTRY ?Stub99@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 99
+ STUBENTRY ?Stub100@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 100
+ STUBENTRY ?Stub101@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 101
+ STUBENTRY ?Stub102@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 102
+ STUBENTRY ?Stub103@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 103
+ STUBENTRY ?Stub104@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 104
+ STUBENTRY ?Stub105@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 105
+ STUBENTRY ?Stub106@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 106
+ STUBENTRY ?Stub107@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 107
+ STUBENTRY ?Stub108@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 108
+ STUBENTRY ?Stub109@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 109
+ STUBENTRY ?Stub110@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 110
+ STUBENTRY ?Stub111@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 111
+ STUBENTRY ?Stub112@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 112
+ STUBENTRY ?Stub113@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 113
+ STUBENTRY ?Stub114@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 114
+ STUBENTRY ?Stub115@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 115
+ STUBENTRY ?Stub116@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 116
+ STUBENTRY ?Stub117@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 117
+ STUBENTRY ?Stub118@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 118
+ STUBENTRY ?Stub119@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 119
+ STUBENTRY ?Stub120@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 120
+ STUBENTRY ?Stub121@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 121
+ STUBENTRY ?Stub122@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 122
+ STUBENTRY ?Stub123@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 123
+ STUBENTRY ?Stub124@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 124
+ STUBENTRY ?Stub125@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 125
+ STUBENTRY ?Stub126@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 126
+ STUBENTRY ?Stub127@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 127
+ STUBENTRY ?Stub128@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 128
+ STUBENTRY ?Stub129@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 129
+ STUBENTRY ?Stub130@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 130
+ STUBENTRY ?Stub131@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 131
+ STUBENTRY ?Stub132@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 132
+ STUBENTRY ?Stub133@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 133
+ STUBENTRY ?Stub134@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 134
+ STUBENTRY ?Stub135@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 135
+ STUBENTRY ?Stub136@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 136
+ STUBENTRY ?Stub137@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 137
+ STUBENTRY ?Stub138@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 138
+ STUBENTRY ?Stub139@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 139
+ STUBENTRY ?Stub140@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 140
+ STUBENTRY ?Stub141@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 141
+ STUBENTRY ?Stub142@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 142
+ STUBENTRY ?Stub143@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 143
+ STUBENTRY ?Stub144@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 144
+ STUBENTRY ?Stub145@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 145
+ STUBENTRY ?Stub146@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 146
+ STUBENTRY ?Stub147@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 147
+ STUBENTRY ?Stub148@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 148
+ STUBENTRY ?Stub149@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 149
+ STUBENTRY ?Stub150@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 150
+ STUBENTRY ?Stub151@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 151
+ STUBENTRY ?Stub152@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 152
+ STUBENTRY ?Stub153@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 153
+ STUBENTRY ?Stub154@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 154
+ STUBENTRY ?Stub155@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 155
+ STUBENTRY ?Stub156@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 156
+ STUBENTRY ?Stub157@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 157
+ STUBENTRY ?Stub158@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 158
+ STUBENTRY ?Stub159@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 159
+ STUBENTRY ?Stub160@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 160
+ STUBENTRY ?Stub161@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 161
+ STUBENTRY ?Stub162@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 162
+ STUBENTRY ?Stub163@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 163
+ STUBENTRY ?Stub164@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 164
+ STUBENTRY ?Stub165@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 165
+ STUBENTRY ?Stub166@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 166
+ STUBENTRY ?Stub167@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 167
+ STUBENTRY ?Stub168@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 168
+ STUBENTRY ?Stub169@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 169
+ STUBENTRY ?Stub170@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 170
+ STUBENTRY ?Stub171@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 171
+ STUBENTRY ?Stub172@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 172
+ STUBENTRY ?Stub173@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 173
+ STUBENTRY ?Stub174@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 174
+ STUBENTRY ?Stub175@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 175
+ STUBENTRY ?Stub176@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 176
+ STUBENTRY ?Stub177@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 177
+ STUBENTRY ?Stub178@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 178
+ STUBENTRY ?Stub179@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 179
+ STUBENTRY ?Stub180@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 180
+ STUBENTRY ?Stub181@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 181
+ STUBENTRY ?Stub182@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 182
+ STUBENTRY ?Stub183@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 183
+ STUBENTRY ?Stub184@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 184
+ STUBENTRY ?Stub185@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 185
+ STUBENTRY ?Stub186@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 186
+ STUBENTRY ?Stub187@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 187
+ STUBENTRY ?Stub188@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 188
+ STUBENTRY ?Stub189@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 189
+ STUBENTRY ?Stub190@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 190
+ STUBENTRY ?Stub191@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 191
+ STUBENTRY ?Stub192@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 192
+ STUBENTRY ?Stub193@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 193
+ STUBENTRY ?Stub194@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 194
+ STUBENTRY ?Stub195@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 195
+ STUBENTRY ?Stub196@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 196
+ STUBENTRY ?Stub197@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 197
+ STUBENTRY ?Stub198@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 198
+ STUBENTRY ?Stub199@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 199
+ STUBENTRY ?Stub200@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 200
+ STUBENTRY ?Stub201@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 201
+ STUBENTRY ?Stub202@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 202
+ STUBENTRY ?Stub203@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 203
+ STUBENTRY ?Stub204@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 204
+ STUBENTRY ?Stub205@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 205
+ STUBENTRY ?Stub206@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 206
+ STUBENTRY ?Stub207@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 207
+ STUBENTRY ?Stub208@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 208
+ STUBENTRY ?Stub209@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 209
+ STUBENTRY ?Stub210@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 210
+ STUBENTRY ?Stub211@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 211
+ STUBENTRY ?Stub212@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 212
+ STUBENTRY ?Stub213@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 213
+ STUBENTRY ?Stub214@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 214
+ STUBENTRY ?Stub215@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 215
+ STUBENTRY ?Stub216@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 216
+ STUBENTRY ?Stub217@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 217
+ STUBENTRY ?Stub218@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 218
+ STUBENTRY ?Stub219@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 219
+ STUBENTRY ?Stub220@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 220
+ STUBENTRY ?Stub221@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 221
+ STUBENTRY ?Stub222@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 222
+ STUBENTRY ?Stub223@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 223
+ STUBENTRY ?Stub224@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 224
+ STUBENTRY ?Stub225@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 225
+ STUBENTRY ?Stub226@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 226
+ STUBENTRY ?Stub227@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 227
+ STUBENTRY ?Stub228@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 228
+ STUBENTRY ?Stub229@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 229
+ STUBENTRY ?Stub230@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 230
+ STUBENTRY ?Stub231@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 231
+ STUBENTRY ?Stub232@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 232
+ STUBENTRY ?Stub233@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 233
+ STUBENTRY ?Stub234@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 234
+ STUBENTRY ?Stub235@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 235
+ STUBENTRY ?Stub236@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 236
+ STUBENTRY ?Stub237@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 237
+ STUBENTRY ?Stub238@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 238
+ STUBENTRY ?Stub239@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 239
+ STUBENTRY ?Stub240@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 240
+ STUBENTRY ?Stub241@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 241
+ STUBENTRY ?Stub242@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 242
+ STUBENTRY ?Stub243@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 243
+ STUBENTRY ?Stub244@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 244
+ STUBENTRY ?Stub245@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 245
+ STUBENTRY ?Stub246@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 246
+ STUBENTRY ?Stub247@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 247
+ STUBENTRY ?Stub248@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 248
+ STUBENTRY ?Stub249@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 249
+
+END
diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp
new file mode 100644
index 0000000000..5f767a3988
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp
@@ -0,0 +1,188 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+/*
+ * This is for Windows XP 64-Bit Edition / Server 2003 for AMD64 or later.
+ */
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args,
+ uint64_t *gprData, double *fprData)
+{
+//
+// "this" pointer is first parameter, so parameter count is 3.
+//
+#define PARAM_GPR_COUNT 3
+#define PARAM_FPR_COUNT 3
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ paramCount = info->GetParamCount();
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint64_t* ap = args;
+ uint32_t iCount = 0;
+
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (iCount < PARAM_GPR_COUNT)
+ iCount++;
+ else
+ ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*)gprData[iCount++];
+ else
+ dp->val.p = (void*)*ap++;
+
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (int8_t)gprData[iCount++];
+ else
+ dp->val.i8 = *((int8_t*)ap++);
+ break;
+
+ case nsXPTType::T_I16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (int16_t)gprData[iCount++];
+ else
+ dp->val.i16 = *((int16_t*)ap++);
+ break;
+
+ case nsXPTType::T_I32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (int32_t)gprData[iCount++];
+ else
+ dp->val.i32 = *((int32_t*)ap++);
+ break;
+
+ case nsXPTType::T_I64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (int64_t)gprData[iCount++];
+ else
+ dp->val.i64 = *((int64_t*)ap++);
+ break;
+
+ case nsXPTType::T_U8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (uint8_t)gprData[iCount++];
+ else
+ dp->val.u8 = *((uint8_t*)ap++);
+ break;
+
+ case nsXPTType::T_U16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (uint16_t)gprData[iCount++];
+ else
+ dp->val.u16 = *((uint16_t*)ap++);
+ break;
+
+ case nsXPTType::T_U32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (uint32_t)gprData[iCount++];
+ else
+ dp->val.u32 = *((uint32_t*)ap++);
+ break;
+
+ case nsXPTType::T_U64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (uint64_t)gprData[iCount++];
+ else
+ dp->val.u64 = *((uint64_t*)ap++);
+ break;
+
+ case nsXPTType::T_FLOAT:
+ if (iCount < PARAM_FPR_COUNT)
+ // The value in xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = (double)fprData[iCount++];
+ else
+ dp->val.f = *((float*)ap++);
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.d = (double)fprData[iCount++];
+ else
+ dp->val.d = *((double*)ap++);
+ break;
+
+ case nsXPTType::T_BOOL:
+ if (iCount < PARAM_GPR_COUNT)
+ // We need the cast to uint8_t to remove garbage on upper 56-bit
+ // at first.
+ dp->val.b = (bool)(uint8_t)gprData[iCount++];
+ else
+ dp->val.b = *((bool*)ap++);
+ break;
+
+ case nsXPTType::T_CHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char)gprData[iCount++];
+ else
+ dp->val.c = *((char*)ap++);
+ break;
+
+ case nsXPTType::T_WCHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t)gprData[iCount++];
+ else
+ dp->val.wc = *((wchar_t*)ap++);
+ break;
+
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+#define STUB_ENTRY(n) /* defined in the assembly file */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+void
+xptc_dummy()
+{
+}
diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp
new file mode 100644
index 0000000000..9c9d245c7f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp
@@ -0,0 +1,297 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xptcprivate.h"
+
+/*
+ * This is for Windows 64 bit (x86_64) using GCC syntax
+ * Code was copied from the MSVC version.
+ */
+
+#if !defined(_AMD64_) || !defined(__GNUC__)
+# error xptcstubs_x86_64_gnu.cpp being used unexpectedly
+#endif
+
+extern "C" nsresult __attribute__((__used__))
+PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex,
+ uint64_t * args, uint64_t * gprData, double *fprData)
+{
+//
+// "this" pointer is first parameter, so parameter count is 3.
+//
+#define PARAM_GPR_COUNT 3
+#define PARAM_FPR_COUNT 3
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self, "no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info, "no method info");
+
+ paramCount = info->GetParamCount();
+
+ //
+ // setup variant array pointer
+ //
+
+ const uint8_t indexOfJSContext = info->IndexOfJSContext();
+
+ uint64_t* ap = args;
+ uint32_t iCount = 0;
+
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &paramBuffer[i];
+
+ if (i == indexOfJSContext) {
+ if (iCount < PARAM_GPR_COUNT)
+ iCount++;
+ else
+ ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*)gprData[iCount++];
+ else
+ dp->val.p = (void*)*ap++;
+
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (int8_t)gprData[iCount++];
+ else
+ dp->val.i8 = *((int8_t*)ap++);
+ break;
+
+ case nsXPTType::T_I16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (int16_t)gprData[iCount++];
+ else
+ dp->val.i16 = *((int16_t*)ap++);
+ break;
+
+ case nsXPTType::T_I32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (int32_t)gprData[iCount++];
+ else
+ dp->val.i32 = *((int32_t*)ap++);
+ break;
+
+ case nsXPTType::T_I64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (int64_t)gprData[iCount++];
+ else
+ dp->val.i64 = *((int64_t*)ap++);
+ break;
+
+ case nsXPTType::T_U8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (uint8_t)gprData[iCount++];
+ else
+ dp->val.u8 = *((uint8_t*)ap++);
+ break;
+
+ case nsXPTType::T_U16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (uint16_t)gprData[iCount++];
+ else
+ dp->val.u16 = *((uint16_t*)ap++);
+ break;
+
+ case nsXPTType::T_U32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (uint32_t)gprData[iCount++];
+ else
+ dp->val.u32 = *((uint32_t*)ap++);
+ break;
+
+ case nsXPTType::T_U64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (uint64_t)gprData[iCount++];
+ else
+ dp->val.u64 = *((uint64_t*)ap++);
+ break;
+
+ case nsXPTType::T_FLOAT:
+ if (iCount < PARAM_FPR_COUNT)
+ // The value in xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = (double)fprData[iCount++];
+ else
+ dp->val.f = *((float*)ap++);
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.d = (double)fprData[iCount++];
+ else
+ dp->val.d = *((double*)ap++);
+ break;
+
+ case nsXPTType::T_BOOL:
+ if (iCount < PARAM_GPR_COUNT)
+ // We need the cast to uint8_t to remove garbage on upper 56-bit
+ // at first.
+ dp->val.b = (bool)(uint8_t)gprData[iCount++];
+ else
+ dp->val.b = *((bool*)ap++);
+ break;
+
+ case nsXPTType::T_CHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char)gprData[iCount++];
+ else
+ dp->val.c = *((char*)ap++);
+ break;
+
+ case nsXPTType::T_WCHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t)gprData[iCount++];
+ else
+ dp->val.wc = *((wchar_t*)ap++);
+ break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info,
+ paramBuffer);
+
+ return result;
+}
+
+__asm__ (
+ ".text\n"
+ ".intel_syntax noprefix\n" /* switch to Intel syntax to look like the MSVC assembly */
+ ".globl SharedStub\n"
+ ".def SharedStub ; .scl 3 ; .type 46 ; .endef \n"
+ "SharedStub:\n"
+ "sub rsp, 104\n"
+
+ /* rcx is this pointer. Need backup for optimized build */
+
+ "mov qword ptr [rsp+88], rcx\n"
+
+ /*
+ * fist 4 parameters (1st is "this" pointer) are passed in registers.
+ */
+
+ /* for floating value */
+
+ "movsd qword ptr [rsp+64], xmm1\n"
+ "movsd qword ptr [rsp+72], xmm2\n"
+ "movsd qword ptr [rsp+80], xmm3\n"
+
+ /* for integer value */
+
+ "mov qword ptr [rsp+40], rdx\n"
+ "mov qword ptr [rsp+48], r8\n"
+ "mov qword ptr [rsp+56], r9\n"
+
+ /*
+ * Call PrepareAndDispatch function
+ */
+
+ /* 5th parameter (floating parameters) of PrepareAndDispatch */
+
+ "lea r9, qword ptr [rsp+64]\n"
+ "mov qword ptr [rsp+32], r9\n"
+
+ /* 4th parameter (normal parameters) of PrepareAndDispatch */
+
+ "lea r9, qword ptr [rsp+40]\n"
+
+ /* 3rd parameter (pointer to args on stack) */
+
+ "lea r8, qword ptr [rsp+40+104]\n"
+
+ /* 2nd parameter (vtbl_index) */
+
+ "mov rdx, r11\n"
+
+ /* 1st parameter (this) (rcx) */
+
+ "call PrepareAndDispatch\n"
+
+ /* restore rcx */
+
+ "mov rcx, qword ptr [rsp+88]\n"
+
+ /*
+ * clean up register
+ */
+
+ "add rsp, 104+8\n"
+
+ /* set return address */
+
+ "mov rdx, qword ptr [rsp-8]\n"
+
+ /* simulate __stdcall return */
+
+ "jmp rdx\n"
+
+ /* back to AT&T syntax */
+ ".att_syntax\n"
+);
+
+#define STUB_ENTRY(n) \
+asm(".intel_syntax noprefix\n" /* this is in intel syntax */ \
+ ".text\n" \
+ ".align 2\n" \
+ ".if " #n " < 10\n" \
+ ".globl _ZN14nsXPTCStubBase5Stub" #n "Ev\n" \
+ ".def _ZN14nsXPTCStubBase5Stub" #n "Ev\n" \
+ ".scl 2\n" /* external */ \
+ ".type 46\n" /* function returning unsigned int */ \
+ ".endef\n" \
+ "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n" \
+ ".elseif " #n " < 100\n" \
+ ".globl _ZN14nsXPTCStubBase6Stub" #n "Ev\n" \
+ ".def _ZN14nsXPTCStubBase6Stub" #n "Ev\n" \
+ ".scl 2\n" /* external */\
+ ".type 46\n" /* function returning unsigned int */ \
+ ".endef\n" \
+ "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n" \
+ ".elseif " #n " < 1000\n" \
+ ".globl _ZN14nsXPTCStubBase7Stub" #n "Ev\n" \
+ ".def _ZN14nsXPTCStubBase7Stub" #n "Ev\n" \
+ ".scl 2\n" /* external */ \
+ ".type 46\n" /* function returning unsigned int */ \
+ ".endef\n" \
+ "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n" \
+ ".else\n" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n" \
+ ".endif\n" \
+ "mov r11, " #n "\n" \
+ "jmp SharedStub\n" \
+ ".att_syntax\n" /* back to AT&T syntax */ \
+ "");
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/moz.build b/xpcom/reflect/xptcall/moz.build
new file mode 100644
index 0000000000..16923a3357
--- /dev/null
+++ b/xpcom/reflect/xptcall/moz.build
@@ -0,0 +1,20 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DIRS += ["md"]
+
+SOURCES += [
+ "xptcall.cpp",
+]
+
+EXPORTS += [
+ "nsXPTCUtils.h",
+ "xptcall.h",
+ "xptcstubsdecl.inc",
+ "xptcstubsdef.inc",
+]
+
+FINAL_LIBRARY = "xul"
diff --git a/xpcom/reflect/xptcall/nsXPTCUtils.h b/xpcom/reflect/xptcall/nsXPTCUtils.h
new file mode 100644
index 0000000000..4f5060360d
--- /dev/null
+++ b/xpcom/reflect/xptcall/nsXPTCUtils.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsXPTCUtils_h__
+#define nsXPTCUtils_h__
+
+#include "xptcall.h"
+#include "mozilla/MemoryReporting.h"
+
+/**
+ * A helper class that initializes an xptcall helper at construction
+ * and releases it at destruction.
+ */
+class nsAutoXPTCStub : protected nsIXPTCProxy {
+ public:
+ nsISomeInterface* mXPTCStub;
+
+ protected:
+ nsAutoXPTCStub() : mXPTCStub(nullptr) {}
+
+ nsresult InitStub(const nsIID& aIID) {
+ return NS_GetXPTCallStub(aIID, this, &mXPTCStub);
+ }
+
+ ~nsAutoXPTCStub() {
+ if (mXPTCStub) {
+ NS_DestroyXPTCallStub(mXPTCStub);
+ }
+ }
+
+ size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
+ return mXPTCStub
+ ? NS_SizeOfIncludingThisXPTCallStub(mXPTCStub, aMallocSizeOf)
+ : 0;
+ }
+};
+
+#endif // nsXPTCUtils_h__
diff --git a/xpcom/reflect/xptcall/porting.html b/xpcom/reflect/xptcall/porting.html
new file mode 100644
index 0000000000..a149aa144a
--- /dev/null
+++ b/xpcom/reflect/xptcall/porting.html
@@ -0,0 +1,237 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<html>
+ <head>
+ <title>xptcall Porting Guide</title>
+ </head>
+ <body bgcolor="white">
+ <h2><center>xptcall Porting Guide</center></h2>
+
+ <h3>Overview</h3>
+
+ <blockquote>
+ <a href="http://www.mozilla.org/scriptable/xptcall-faq.html"> xptcall</a>
+ is a library that supports both invoking methods on arbitrary xpcom
+ objects and implementing classes whose objects can impersonate any xpcom
+ interface. It does this using platform specific assembly language code.
+ This code needs to be ported to all platforms that want to support xptcall
+ (and thus mozilla).
+ </blockquote>
+
+ <h3>The tree</h3>
+
+ <blockquote>
+ <pre>
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall">mozilla/xpcom/reflect/xptcall</a>
+ +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public">public</a> // exported headers
+ +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src">src</a> // core source
+ | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md">md</a> // platform specific parts
+ | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/mac">mac</a> // mac ppc
+ | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> // all unix
+ | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32">win32</a> // win32
+ | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/test">test</a> // simple tests to get started
+ \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests">tests</a> // full tests via api
+</pre>
+
+ Porters are free to create subdirectories under the base <code>md</code>
+ directory for their given platforms and to integrate into the build system
+ as appropriate for their platform.
+ </blockquote>
+
+ <h3>Theory of operation</h3>
+
+ <blockquote>
+ There are really two pieces of functionality: <i>invoke</i> and
+ <i>stubs</i>...
+
+ <p>
+ The <b><i>invoke</i></b> functionality requires the implementation of
+ the following on each platform (from
+ <a
+ href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcall.h"
+ >xptcall/xptcall.h</a
+ >):
+ </p>
+
+ <pre>
+XPTC_PUBLIC_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+</pre
+ >
+
+ Calling code is expected to supply an array of
+ <code>nsXPTCVariant</code> structs. These are discriminated unions
+ describing the type and value of each parameter of the target function.
+ The platform specific code then builds a call frame and invokes the method
+ indicated by the index <code>methodIndex</code> on the xpcom interface
+ <code>that</code>.
+
+ <p>
+ Here are examples of this implementation for
+ <a
+ href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp"
+ >Win32</a
+ >
+ and
+ <a
+ href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix/xptcinvoke_unixish_x86.cpp"
+ >Linux x86, NetBSD x86, and FreeBSD</a
+ >. Both of these implementations use the basic strategy of: figure out
+ how much stack space is needed for the params, make the space in a new
+ frame, copy the params to that space, invoke the method, cleanup and
+ return. C++ is used where appropriate, Assembly language is used where
+ necessary. Inline assembly language is used here, but it is equally
+ valid to use separate assembly language source files. Porters can decide
+ how best to do this for their platforms.
+ </p>
+
+ <p>
+ The <b><i>stubs</i></b> functionality is more complex. The goal here is
+ a class whose vtbl can look like the vtbl of any arbitrary xpcom
+ interface. Objects of this class can then be built to impersonate any
+ xpcom object. The base interface for this is (from
+ <a
+ href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcall.h"
+ >xptcall/xptcall.h</a
+ >):
+ </p>
+
+ <pre>
+class nsXPTCStubBase : public nsISupports
+{
+public:
+ // Include generated vtbl stub declarations.
+ // These are virtual and *also* implemented by this class..
+#include "xptcstubsdecl.inc"
+
+ // The following methods must be provided by inheritor of this class.
+
+ // return a refcounted pointer to the InterfaceInfo for this object
+ // NOTE: on some platforms this MUST not fail or we crash!
+ NS_IMETHOD GetInterfaceInfo(const nsXPTInterfaceInfo** info) = 0;
+
+ // call this method and return result
+ NS_IMETHOD CallMethod(uint16_t methodIndex,
+ const nsXPTMethodInfo* info,
+ nsXPTCMiniVariant* params) = 0;
+};
+</pre
+ >
+
+ Code that wishes to make use of this <i>stubs</i> functionality (such as
+ <a href="http://www.mozilla.org/scriptable/">XPConnect</a>) implement a
+ class which inherits from <code>nsXPTCStubBase</code> and implements the
+ <code>GetInterfaceInfo</code> and <code>CallMethod</code> to let the
+ platform specific code know how to get interface information and how to
+ dispatch methods once their parameters have been pulled out of the
+ platform specific calling frame.
+
+ <p>
+ Porters of this functionality implement the platform specific code for
+ the
+ <i>stub</i> methods that fill the vtbl for this class. The idea here is
+ that the class has a vtbl full of a large number of generic stubs. All
+ instances of this class share that vtbl and the same stubs. The stubs
+ forward calls to a platform specific method that uses the interface
+ information supplied by the overridden <code>GetInterfaceInfo</code> to
+ extract the parameters and build an array of platform independent
+ <code>nsXPTCMiniVariant</code> structs which are in turn passed on to
+ the overridden <code>CallMethod</code>. The platform dependent code is
+ responsible for doing any cleanup and returning.
+ </p>
+
+ <p>
+ The stub methods are declared in
+ <a
+ href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcstubsdecl.inc"
+ >xptcall/xptcstubsdecl.inc</a
+ >. These are '#included' into the declaration of
+ <code>nsXPTCStubBase</code>. A similar include file (<a
+ href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcstubsdef.inc"
+ >xptcall/xptcstubsdef.inc</a
+ >) is expanded using platform specific macros to define the stub
+ functions. These '.inc' files are checked into cvs. However, they can be
+ regenerated as necessary (i.e. to change the number of stubs or to
+ change their specific declaration) using the Perl script
+ <a
+ href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/genstubs.pl"
+ >xptcall/genstubs.pl</a
+ >.
+ </p>
+
+ <p>
+ Here are examples of this implementation for
+ <a
+ href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp"
+ >Win32</a
+ >
+ and
+ <a
+ href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix/xptcstubs_unixish_x86.cpp"
+ >Linux x86, NetBSD x86, and FreeBSD</a
+ >. Both of these examples use inline assembly language. That is just how
+ I decided to do it. You can do it as you choose.
+ </p>
+
+ <p>
+ The Win32 version is somewhat tighter because the __declspec(naked)
+ feature allows for very small stubs. However, the __stdcall requires the
+ callee to clean up the stack, so it is imperative that the interface
+ information scheme allow the code to determine the correct stack pointer
+ fixup for return without fail, else the process will crash.
+ </p>
+
+ <p>
+ I opted to use inline assembler for the gcc Linux x86 port. I ended up
+ with larger stubs than I would have preferred rather than battle the
+ compiler over what would happen to the stack before my asm code began
+ running.
+ </p>
+
+ <p>
+ I believe that the non-assembly parts of these files can be copied and
+ reused with minimal (but not zero) platform specific tweaks. Feel free
+ to copy and paste as necessary. Please remember that safety and
+ reliability are more important than speed optimizations. This code is
+ primarily used to connect XPCOM components with JavaScript; function
+ call overhead is a <b>tiny</b> part of the time involved.
+ </p>
+
+ <p>
+ I put together
+ <a
+ href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/test"
+ >xptcall/md/test
+ </a>
+ as a place to evolve the basic functionality as a port is coming
+ together. Not all of the functionality is exercised, but it is a place
+ to get started.
+ <a
+ href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests"
+ >xptcall/tests
+ </a>
+ has an api level test for <code>NS_InvokeByIndex</code>, but no tests
+ for the <i>stubs</i> functionality. Such a test ought to be written, but
+ this has not yet been done.
+ </p>
+
+ <p>
+ A full 'test' at this point requires building the client and running the
+ XPConnect test called <i>TestXPC</i> in
+ <a href="http://lxr.mozilla.org/mozilla/source/js/xpconnect/tests"
+ >mozilla/js/xpconnect/tests </a
+ >.
+ </p>
+ </blockquote>
+
+ <hr />
+ <b>Author:</b>
+ <a href="mailto:jband@netscape.com"
+ >John Bandhauer &lt;jband@netscape.com&gt;</a
+ ><br />
+ <b>Last modified:</b> 31 May 1999
+ </body>
+</html>
diff --git a/xpcom/reflect/xptcall/xptcall.cpp b/xpcom/reflect/xptcall/xptcall.cpp
new file mode 100644
index 0000000000..0b28791b54
--- /dev/null
+++ b/xpcom/reflect/xptcall/xptcall.cpp
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* entry point wrappers. */
+
+#include "xptcprivate.h"
+
+using namespace mozilla;
+
+NS_IMETHODIMP
+nsXPTCStubBase::QueryInterface(REFNSIID aIID, void** aInstancePtr) {
+ if (aIID.Equals(mEntry->IID())) {
+ NS_ADDREF_THIS();
+ *aInstancePtr = static_cast<nsISupports*>(this);
+ return NS_OK;
+ }
+
+ return mOuter->QueryInterface(aIID, aInstancePtr);
+}
+
+NS_IMETHODIMP_(MozExternalRefCountType)
+nsXPTCStubBase::AddRef() { return mOuter->AddRef(); }
+
+NS_IMETHODIMP_(MozExternalRefCountType)
+nsXPTCStubBase::Release() { return mOuter->Release(); }
+
+EXPORT_XPCOM_API(nsresult)
+NS_GetXPTCallStub(REFNSIID aIID, nsIXPTCProxy* aOuter,
+ nsISomeInterface** aResult) {
+ if (NS_WARN_IF(!aOuter) || NS_WARN_IF(!aResult)) return NS_ERROR_INVALID_ARG;
+
+ const nsXPTInterfaceInfo* iie = nsXPTInterfaceInfo::ByIID(aIID);
+ if (!iie || iie->IsBuiltinClass()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ *aResult = new nsXPTCStubBase(aOuter, iie);
+ return NS_OK;
+}
+
+EXPORT_XPCOM_API(void)
+NS_DestroyXPTCallStub(nsISomeInterface* aStub) {
+ nsXPTCStubBase* stub = static_cast<nsXPTCStubBase*>(aStub);
+ delete (stub);
+}
+
+EXPORT_XPCOM_API(size_t)
+NS_SizeOfIncludingThisXPTCallStub(const nsISomeInterface* aStub,
+ mozilla::MallocSizeOf aMallocSizeOf) {
+ // We could cast aStub to nsXPTCStubBase, but that class doesn't seem to own
+ // anything, so just measure the size of the object itself.
+ return aMallocSizeOf(aStub);
+}
diff --git a/xpcom/reflect/xptcall/xptcall.h b/xpcom/reflect/xptcall/xptcall.h
new file mode 100644
index 0000000000..a36ca53d23
--- /dev/null
+++ b/xpcom/reflect/xptcall/xptcall.h
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Public declarations for xptcall. */
+
+#ifndef xptcall_h___
+#define xptcall_h___
+
+#include "nscore.h"
+#include "nsISupports.h"
+#include "xptinfo.h"
+#include "js/Value.h"
+#include "mozilla/MemoryReporting.h"
+
+struct nsXPTCMiniVariant {
+ // No ctors or dtors so that we can use arrays of these on the stack
+ // with no penalty.
+ union Union {
+ int8_t i8;
+ int16_t i16;
+ int32_t i32;
+ int64_t i64;
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ uint64_t u64;
+ float f;
+ double d;
+ bool b;
+ char c;
+ char16_t wc;
+ void* p;
+ };
+
+ Union val;
+};
+
+static_assert(offsetof(nsXPTCMiniVariant, val) == 0,
+ "nsXPTCMiniVariant must be a thin wrapper");
+
+struct nsXPTCVariant {
+ union ExtendedVal {
+ // ExtendedVal is an extension on nsXPTCMiniVariant. It contains types
+ // unknown to the assembly implementations which must be passed by indirect
+ // semantics.
+ //
+ // nsXPTCVariant contains enough space to store ExtendedVal inline, which
+ // can be used to store these types when IsIndirect() is true.
+ nsXPTCMiniVariant mini;
+
+ nsID nsid;
+ nsCString nscstr;
+ nsString nsstr;
+ JS::Value jsval;
+ xpt::detail::UntypedTArray array;
+
+ // This type contains non-standard-layout types, so needs an explicit
+ // Ctor/Dtor - we'll just delete them.
+ ExtendedVal() = delete;
+ ~ExtendedVal() = delete;
+ };
+
+ union {
+ // The `val` field from nsXPTCMiniVariant.
+ nsXPTCMiniVariant::Union val;
+
+ // Storage for any extended variants.
+ ExtendedVal ext;
+ };
+
+ nsXPTType type;
+ uint8_t flags;
+
+ // Clear to a valid, null state.
+ nsXPTCVariant() {
+ memset(this, 0, sizeof(nsXPTCVariant));
+ type = nsXPTType::T_VOID;
+ }
+
+ enum {
+ //
+ // Bitflag definitions
+ //
+
+ // Indicates that we &val.p should be passed n the stack, i.e. that
+ // val should be passed by reference.
+ IS_INDIRECT = 0x1,
+ };
+
+ void ClearFlags() { flags = 0; }
+ void SetIndirect() { flags |= IS_INDIRECT; }
+
+ bool IsIndirect() const { return 0 != (flags & IS_INDIRECT); }
+
+ // Implicitly convert to nsXPTCMiniVariant.
+ operator nsXPTCMiniVariant&() { return *(nsXPTCMiniVariant*)&val; }
+ operator const nsXPTCMiniVariant&() const {
+ return *(const nsXPTCMiniVariant*)&val;
+ }
+
+ // As this type contains an anonymous union, we need to provide an explicit
+ // destructor.
+ ~nsXPTCVariant() {}
+};
+
+static_assert(offsetof(nsXPTCVariant, val) == offsetof(nsXPTCVariant, ext),
+ "nsXPTCVariant::{ext,val} must have matching offsets");
+
+// static_assert that nsXPTCVariant::ExtendedVal is large enough and
+// well-aligned enough for every XPT-supported type.
+#define XPT_CHECK_SIZEOF(xpt, type) \
+ static_assert(sizeof(nsXPTCVariant::ExtendedVal) >= sizeof(type), \
+ "nsXPTCVariant::ext not big enough for " #xpt " (" #type ")"); \
+ static_assert(MOZ_ALIGNOF(nsXPTCVariant::ExtendedVal) >= MOZ_ALIGNOF(type), \
+ "nsXPTCVariant::ext not aligned enough for " #xpt " (" #type \
+ ")");
+XPT_FOR_EACH_TYPE(XPT_CHECK_SIZEOF)
+#undef XPT_CHECK_SIZEOF
+
+class nsIXPTCProxy : public nsISupports {
+ public:
+ NS_IMETHOD CallMethod(uint16_t aMethodIndex, const nsXPTMethodInfo* aInfo,
+ nsXPTCMiniVariant* aParams) = 0;
+};
+
+/**
+ * This is a typedef to avoid confusion between the canonical
+ * nsISupports* that provides object identity and an interface pointer
+ * for inheriting interfaces that aren't known at compile-time.
+ */
+typedef nsISupports nsISomeInterface;
+
+/**
+ * Get a proxy object to implement the specified interface.
+ *
+ * @param aIID The IID of the interface to implement.
+ * @param aOuter An object to receive method calls from the proxy object.
+ * The stub forwards QueryInterface/AddRef/Release to the
+ * outer object. The proxy object does not hold a reference to
+ * the outer object; it is the caller's responsibility to
+ * ensure that this pointer remains valid until the stub has
+ * been destroyed.
+ * @param aStub Out parameter for the new proxy object. The object is
+ * not addrefed. The object never destroys itself. It must be
+ * explicitly destroyed by calling
+ * NS_DestroyXPTCallStub when it is no longer needed.
+ */
+XPCOM_API(nsresult)
+NS_GetXPTCallStub(REFNSIID aIID, nsIXPTCProxy* aOuter,
+ nsISomeInterface** aStub);
+
+/**
+ * Destroys an XPTCall stub previously created with NS_GetXPTCallStub.
+ */
+XPCOM_API(void)
+NS_DestroyXPTCallStub(nsISomeInterface* aStub);
+
+/**
+ * Measures the size of an XPTCall stub previously created with
+ * NS_GetXPTCallStub.
+ */
+XPCOM_API(size_t)
+NS_SizeOfIncludingThisXPTCallStub(const nsISomeInterface* aStub,
+ mozilla::MallocSizeOf aMallocSizeOf);
+
+// this is extern "C" because on some platforms it is implemented in assembly
+extern "C" nsresult NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount,
+ nsXPTCVariant* params);
+
+#endif /* xptcall_h___ */
diff --git a/xpcom/reflect/xptcall/xptcprivate.h b/xpcom/reflect/xptcall/xptcprivate.h
new file mode 100644
index 0000000000..02f408dc38
--- /dev/null
+++ b/xpcom/reflect/xptcall/xptcprivate.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* All the xptcall private declarations - only include locally. */
+
+#ifndef xptcprivate_h___
+#define xptcprivate_h___
+
+#include "xptcall.h"
+#include "mozilla/Attributes.h"
+
+#if !defined(__ia64) || \
+ (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__))
+# define STUB_ENTRY(n) NS_IMETHOD Stub##n() = 0;
+#else
+# define STUB_ENTRY(n) \
+ NS_IMETHOD Stub##n(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, \
+ uint64_t, uint64_t, uint64_t) = 0;
+#endif
+
+#define SENTINEL_ENTRY(n) NS_IMETHOD Sentinel##n() = 0;
+
+class nsIXPTCStubBase : public nsISupports {
+ public:
+#include "xptcstubsdef.inc"
+};
+
+#undef STUB_ENTRY
+#undef SENTINEL_ENTRY
+
+#if !defined(__ia64) || \
+ (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__))
+# define STUB_ENTRY(n) NS_IMETHOD Stub##n() override;
+#else
+# define STUB_ENTRY(n) \
+ NS_IMETHOD Stub##n(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, \
+ uint64_t, uint64_t, uint64_t) override;
+#endif
+
+#define SENTINEL_ENTRY(n) NS_IMETHOD Sentinel##n() override;
+
+class nsXPTCStubBase final : public nsIXPTCStubBase {
+ public:
+ NS_DECL_ISUPPORTS_INHERITED
+
+#include "xptcstubsdef.inc"
+
+ nsXPTCStubBase(nsIXPTCProxy* aOuter, const nsXPTInterfaceInfo* aEntry)
+ : mOuter(aOuter), mEntry(aEntry) {}
+
+ nsIXPTCProxy* mOuter;
+ const nsXPTInterfaceInfo* mEntry;
+
+ ~nsXPTCStubBase() = default;
+};
+
+#undef STUB_ENTRY
+#undef SENTINEL_ENTRY
+
+#if defined(__clang__) || defined(__GNUC__)
+# define ATTRIBUTE_USED __attribute__((__used__))
+#else
+# define ATTRIBUTE_USED
+#endif
+
+#endif /* xptcprivate_h___ */
diff --git a/xpcom/reflect/xptcall/xptcstubsdecl.inc b/xpcom/reflect/xptcall/xptcstubsdecl.inc
new file mode 100644
index 0000000000..91d35fe322
--- /dev/null
+++ b/xpcom/reflect/xptcall/xptcstubsdecl.inc
@@ -0,0 +1,761 @@
+/* generated file - DO NOT EDIT */
+
+/* includes 247 stub entries, and 5 sentinel entries */
+
+/*
+* declarations of normal stubs...
+* 0 is QueryInterface
+* 1 is AddRef
+* 2 is Release
+*/
+#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__))
+NS_IMETHOD Stub3();
+NS_IMETHOD Stub4();
+NS_IMETHOD Stub5();
+NS_IMETHOD Stub6();
+NS_IMETHOD Stub7();
+NS_IMETHOD Stub8();
+NS_IMETHOD Stub9();
+NS_IMETHOD Stub10();
+NS_IMETHOD Stub11();
+NS_IMETHOD Stub12();
+NS_IMETHOD Stub13();
+NS_IMETHOD Stub14();
+NS_IMETHOD Stub15();
+NS_IMETHOD Stub16();
+NS_IMETHOD Stub17();
+NS_IMETHOD Stub18();
+NS_IMETHOD Stub19();
+NS_IMETHOD Stub20();
+NS_IMETHOD Stub21();
+NS_IMETHOD Stub22();
+NS_IMETHOD Stub23();
+NS_IMETHOD Stub24();
+NS_IMETHOD Stub25();
+NS_IMETHOD Stub26();
+NS_IMETHOD Stub27();
+NS_IMETHOD Stub28();
+NS_IMETHOD Stub29();
+NS_IMETHOD Stub30();
+NS_IMETHOD Stub31();
+NS_IMETHOD Stub32();
+NS_IMETHOD Stub33();
+NS_IMETHOD Stub34();
+NS_IMETHOD Stub35();
+NS_IMETHOD Stub36();
+NS_IMETHOD Stub37();
+NS_IMETHOD Stub38();
+NS_IMETHOD Stub39();
+NS_IMETHOD Stub40();
+NS_IMETHOD Stub41();
+NS_IMETHOD Stub42();
+NS_IMETHOD Stub43();
+NS_IMETHOD Stub44();
+NS_IMETHOD Stub45();
+NS_IMETHOD Stub46();
+NS_IMETHOD Stub47();
+NS_IMETHOD Stub48();
+NS_IMETHOD Stub49();
+NS_IMETHOD Stub50();
+NS_IMETHOD Stub51();
+NS_IMETHOD Stub52();
+NS_IMETHOD Stub53();
+NS_IMETHOD Stub54();
+NS_IMETHOD Stub55();
+NS_IMETHOD Stub56();
+NS_IMETHOD Stub57();
+NS_IMETHOD Stub58();
+NS_IMETHOD Stub59();
+NS_IMETHOD Stub60();
+NS_IMETHOD Stub61();
+NS_IMETHOD Stub62();
+NS_IMETHOD Stub63();
+NS_IMETHOD Stub64();
+NS_IMETHOD Stub65();
+NS_IMETHOD Stub66();
+NS_IMETHOD Stub67();
+NS_IMETHOD Stub68();
+NS_IMETHOD Stub69();
+NS_IMETHOD Stub70();
+NS_IMETHOD Stub71();
+NS_IMETHOD Stub72();
+NS_IMETHOD Stub73();
+NS_IMETHOD Stub74();
+NS_IMETHOD Stub75();
+NS_IMETHOD Stub76();
+NS_IMETHOD Stub77();
+NS_IMETHOD Stub78();
+NS_IMETHOD Stub79();
+NS_IMETHOD Stub80();
+NS_IMETHOD Stub81();
+NS_IMETHOD Stub82();
+NS_IMETHOD Stub83();
+NS_IMETHOD Stub84();
+NS_IMETHOD Stub85();
+NS_IMETHOD Stub86();
+NS_IMETHOD Stub87();
+NS_IMETHOD Stub88();
+NS_IMETHOD Stub89();
+NS_IMETHOD Stub90();
+NS_IMETHOD Stub91();
+NS_IMETHOD Stub92();
+NS_IMETHOD Stub93();
+NS_IMETHOD Stub94();
+NS_IMETHOD Stub95();
+NS_IMETHOD Stub96();
+NS_IMETHOD Stub97();
+NS_IMETHOD Stub98();
+NS_IMETHOD Stub99();
+NS_IMETHOD Stub100();
+NS_IMETHOD Stub101();
+NS_IMETHOD Stub102();
+NS_IMETHOD Stub103();
+NS_IMETHOD Stub104();
+NS_IMETHOD Stub105();
+NS_IMETHOD Stub106();
+NS_IMETHOD Stub107();
+NS_IMETHOD Stub108();
+NS_IMETHOD Stub109();
+NS_IMETHOD Stub110();
+NS_IMETHOD Stub111();
+NS_IMETHOD Stub112();
+NS_IMETHOD Stub113();
+NS_IMETHOD Stub114();
+NS_IMETHOD Stub115();
+NS_IMETHOD Stub116();
+NS_IMETHOD Stub117();
+NS_IMETHOD Stub118();
+NS_IMETHOD Stub119();
+NS_IMETHOD Stub120();
+NS_IMETHOD Stub121();
+NS_IMETHOD Stub122();
+NS_IMETHOD Stub123();
+NS_IMETHOD Stub124();
+NS_IMETHOD Stub125();
+NS_IMETHOD Stub126();
+NS_IMETHOD Stub127();
+NS_IMETHOD Stub128();
+NS_IMETHOD Stub129();
+NS_IMETHOD Stub130();
+NS_IMETHOD Stub131();
+NS_IMETHOD Stub132();
+NS_IMETHOD Stub133();
+NS_IMETHOD Stub134();
+NS_IMETHOD Stub135();
+NS_IMETHOD Stub136();
+NS_IMETHOD Stub137();
+NS_IMETHOD Stub138();
+NS_IMETHOD Stub139();
+NS_IMETHOD Stub140();
+NS_IMETHOD Stub141();
+NS_IMETHOD Stub142();
+NS_IMETHOD Stub143();
+NS_IMETHOD Stub144();
+NS_IMETHOD Stub145();
+NS_IMETHOD Stub146();
+NS_IMETHOD Stub147();
+NS_IMETHOD Stub148();
+NS_IMETHOD Stub149();
+NS_IMETHOD Stub150();
+NS_IMETHOD Stub151();
+NS_IMETHOD Stub152();
+NS_IMETHOD Stub153();
+NS_IMETHOD Stub154();
+NS_IMETHOD Stub155();
+NS_IMETHOD Stub156();
+NS_IMETHOD Stub157();
+NS_IMETHOD Stub158();
+NS_IMETHOD Stub159();
+NS_IMETHOD Stub160();
+NS_IMETHOD Stub161();
+NS_IMETHOD Stub162();
+NS_IMETHOD Stub163();
+NS_IMETHOD Stub164();
+NS_IMETHOD Stub165();
+NS_IMETHOD Stub166();
+NS_IMETHOD Stub167();
+NS_IMETHOD Stub168();
+NS_IMETHOD Stub169();
+NS_IMETHOD Stub170();
+NS_IMETHOD Stub171();
+NS_IMETHOD Stub172();
+NS_IMETHOD Stub173();
+NS_IMETHOD Stub174();
+NS_IMETHOD Stub175();
+NS_IMETHOD Stub176();
+NS_IMETHOD Stub177();
+NS_IMETHOD Stub178();
+NS_IMETHOD Stub179();
+NS_IMETHOD Stub180();
+NS_IMETHOD Stub181();
+NS_IMETHOD Stub182();
+NS_IMETHOD Stub183();
+NS_IMETHOD Stub184();
+NS_IMETHOD Stub185();
+NS_IMETHOD Stub186();
+NS_IMETHOD Stub187();
+NS_IMETHOD Stub188();
+NS_IMETHOD Stub189();
+NS_IMETHOD Stub190();
+NS_IMETHOD Stub191();
+NS_IMETHOD Stub192();
+NS_IMETHOD Stub193();
+NS_IMETHOD Stub194();
+NS_IMETHOD Stub195();
+NS_IMETHOD Stub196();
+NS_IMETHOD Stub197();
+NS_IMETHOD Stub198();
+NS_IMETHOD Stub199();
+NS_IMETHOD Stub200();
+NS_IMETHOD Stub201();
+NS_IMETHOD Stub202();
+NS_IMETHOD Stub203();
+NS_IMETHOD Stub204();
+NS_IMETHOD Stub205();
+NS_IMETHOD Stub206();
+NS_IMETHOD Stub207();
+NS_IMETHOD Stub208();
+NS_IMETHOD Stub209();
+NS_IMETHOD Stub210();
+NS_IMETHOD Stub211();
+NS_IMETHOD Stub212();
+NS_IMETHOD Stub213();
+NS_IMETHOD Stub214();
+NS_IMETHOD Stub215();
+NS_IMETHOD Stub216();
+NS_IMETHOD Stub217();
+NS_IMETHOD Stub218();
+NS_IMETHOD Stub219();
+NS_IMETHOD Stub220();
+NS_IMETHOD Stub221();
+NS_IMETHOD Stub222();
+NS_IMETHOD Stub223();
+NS_IMETHOD Stub224();
+NS_IMETHOD Stub225();
+NS_IMETHOD Stub226();
+NS_IMETHOD Stub227();
+NS_IMETHOD Stub228();
+NS_IMETHOD Stub229();
+NS_IMETHOD Stub230();
+NS_IMETHOD Stub231();
+NS_IMETHOD Stub232();
+NS_IMETHOD Stub233();
+NS_IMETHOD Stub234();
+NS_IMETHOD Stub235();
+NS_IMETHOD Stub236();
+NS_IMETHOD Stub237();
+NS_IMETHOD Stub238();
+NS_IMETHOD Stub239();
+NS_IMETHOD Stub240();
+NS_IMETHOD Stub241();
+NS_IMETHOD Stub242();
+NS_IMETHOD Stub243();
+NS_IMETHOD Stub244();
+NS_IMETHOD Stub245();
+NS_IMETHOD Stub246();
+NS_IMETHOD Stub247();
+NS_IMETHOD Stub248();
+NS_IMETHOD Stub249();
+#else
+NS_IMETHOD Stub3(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub4(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub5(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub6(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub7(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub8(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub9(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub10(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub11(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub12(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub13(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub14(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub15(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub16(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub17(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub18(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub19(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub20(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub21(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub22(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub23(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub24(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub25(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub26(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub27(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub28(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub29(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub30(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub31(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub32(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub33(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub34(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub35(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub36(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub37(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub38(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub39(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub40(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub41(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub42(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub43(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub44(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub45(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub46(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub47(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub48(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub49(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub50(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub51(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub52(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub53(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub54(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub55(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub56(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub57(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub58(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub59(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub60(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub61(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub62(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub63(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub64(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub65(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub66(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub67(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub68(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub69(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub70(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub71(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub72(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub73(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub74(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub75(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub76(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub77(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub78(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub79(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub80(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub81(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub82(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub83(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub84(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub85(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub86(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub87(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub88(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub89(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub90(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub91(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub92(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub93(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub94(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub95(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub96(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub97(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub98(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub99(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub100(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub101(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub102(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub103(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub104(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub105(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub106(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub107(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub108(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub109(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub110(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub111(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub112(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub113(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub114(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub115(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub116(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub117(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub118(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub119(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub120(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub121(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub122(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub123(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub124(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub125(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub126(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub127(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub128(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub129(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub130(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub131(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub132(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub133(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub134(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub135(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub136(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub137(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub138(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub139(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub140(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub141(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub142(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub143(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub144(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub145(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub146(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub147(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub148(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub149(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub150(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub151(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub152(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub153(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub154(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub155(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub156(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub157(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub158(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub159(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub160(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub161(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub162(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub163(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub164(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub165(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub166(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub167(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub168(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub169(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub170(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub171(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub172(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub173(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub174(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub175(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub176(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub177(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub178(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub179(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub180(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub181(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub182(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub183(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub184(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub185(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub186(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub187(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub188(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub189(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub190(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub191(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub192(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub193(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub194(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub195(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub196(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub197(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub198(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub199(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub200(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub201(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub202(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub203(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub204(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub205(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub206(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub207(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub208(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub209(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub210(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub211(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub212(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub213(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub214(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub215(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub216(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub217(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub218(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub219(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub220(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub221(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub222(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub223(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub224(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub225(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub226(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub227(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub228(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub229(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub230(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub231(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub232(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub233(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub234(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub235(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub236(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub237(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub238(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub239(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub240(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub241(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub242(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub243(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub244(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub245(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub246(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub247(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub248(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+NS_IMETHOD Stub249(uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);
+#endif
+
+/* declarations of sentinel stubs */
+NS_IMETHOD Sentinel0();
+NS_IMETHOD Sentinel1();
+NS_IMETHOD Sentinel2();
+NS_IMETHOD Sentinel3();
+NS_IMETHOD Sentinel4();
diff --git a/xpcom/reflect/xptcall/xptcstubsdef.inc b/xpcom/reflect/xptcall/xptcstubsdef.inc
new file mode 100644
index 0000000000..2df455406a
--- /dev/null
+++ b/xpcom/reflect/xptcall/xptcstubsdef.inc
@@ -0,0 +1,252 @@
+STUB_ENTRY(3)
+STUB_ENTRY(4)
+STUB_ENTRY(5)
+STUB_ENTRY(6)
+STUB_ENTRY(7)
+STUB_ENTRY(8)
+STUB_ENTRY(9)
+STUB_ENTRY(10)
+STUB_ENTRY(11)
+STUB_ENTRY(12)
+STUB_ENTRY(13)
+STUB_ENTRY(14)
+STUB_ENTRY(15)
+STUB_ENTRY(16)
+STUB_ENTRY(17)
+STUB_ENTRY(18)
+STUB_ENTRY(19)
+STUB_ENTRY(20)
+STUB_ENTRY(21)
+STUB_ENTRY(22)
+STUB_ENTRY(23)
+STUB_ENTRY(24)
+STUB_ENTRY(25)
+STUB_ENTRY(26)
+STUB_ENTRY(27)
+STUB_ENTRY(28)
+STUB_ENTRY(29)
+STUB_ENTRY(30)
+STUB_ENTRY(31)
+STUB_ENTRY(32)
+STUB_ENTRY(33)
+STUB_ENTRY(34)
+STUB_ENTRY(35)
+STUB_ENTRY(36)
+STUB_ENTRY(37)
+STUB_ENTRY(38)
+STUB_ENTRY(39)
+STUB_ENTRY(40)
+STUB_ENTRY(41)
+STUB_ENTRY(42)
+STUB_ENTRY(43)
+STUB_ENTRY(44)
+STUB_ENTRY(45)
+STUB_ENTRY(46)
+STUB_ENTRY(47)
+STUB_ENTRY(48)
+STUB_ENTRY(49)
+STUB_ENTRY(50)
+STUB_ENTRY(51)
+STUB_ENTRY(52)
+STUB_ENTRY(53)
+STUB_ENTRY(54)
+STUB_ENTRY(55)
+STUB_ENTRY(56)
+STUB_ENTRY(57)
+STUB_ENTRY(58)
+STUB_ENTRY(59)
+STUB_ENTRY(60)
+STUB_ENTRY(61)
+STUB_ENTRY(62)
+STUB_ENTRY(63)
+STUB_ENTRY(64)
+STUB_ENTRY(65)
+STUB_ENTRY(66)
+STUB_ENTRY(67)
+STUB_ENTRY(68)
+STUB_ENTRY(69)
+STUB_ENTRY(70)
+STUB_ENTRY(71)
+STUB_ENTRY(72)
+STUB_ENTRY(73)
+STUB_ENTRY(74)
+STUB_ENTRY(75)
+STUB_ENTRY(76)
+STUB_ENTRY(77)
+STUB_ENTRY(78)
+STUB_ENTRY(79)
+STUB_ENTRY(80)
+STUB_ENTRY(81)
+STUB_ENTRY(82)
+STUB_ENTRY(83)
+STUB_ENTRY(84)
+STUB_ENTRY(85)
+STUB_ENTRY(86)
+STUB_ENTRY(87)
+STUB_ENTRY(88)
+STUB_ENTRY(89)
+STUB_ENTRY(90)
+STUB_ENTRY(91)
+STUB_ENTRY(92)
+STUB_ENTRY(93)
+STUB_ENTRY(94)
+STUB_ENTRY(95)
+STUB_ENTRY(96)
+STUB_ENTRY(97)
+STUB_ENTRY(98)
+STUB_ENTRY(99)
+STUB_ENTRY(100)
+STUB_ENTRY(101)
+STUB_ENTRY(102)
+STUB_ENTRY(103)
+STUB_ENTRY(104)
+STUB_ENTRY(105)
+STUB_ENTRY(106)
+STUB_ENTRY(107)
+STUB_ENTRY(108)
+STUB_ENTRY(109)
+STUB_ENTRY(110)
+STUB_ENTRY(111)
+STUB_ENTRY(112)
+STUB_ENTRY(113)
+STUB_ENTRY(114)
+STUB_ENTRY(115)
+STUB_ENTRY(116)
+STUB_ENTRY(117)
+STUB_ENTRY(118)
+STUB_ENTRY(119)
+STUB_ENTRY(120)
+STUB_ENTRY(121)
+STUB_ENTRY(122)
+STUB_ENTRY(123)
+STUB_ENTRY(124)
+STUB_ENTRY(125)
+STUB_ENTRY(126)
+STUB_ENTRY(127)
+STUB_ENTRY(128)
+STUB_ENTRY(129)
+STUB_ENTRY(130)
+STUB_ENTRY(131)
+STUB_ENTRY(132)
+STUB_ENTRY(133)
+STUB_ENTRY(134)
+STUB_ENTRY(135)
+STUB_ENTRY(136)
+STUB_ENTRY(137)
+STUB_ENTRY(138)
+STUB_ENTRY(139)
+STUB_ENTRY(140)
+STUB_ENTRY(141)
+STUB_ENTRY(142)
+STUB_ENTRY(143)
+STUB_ENTRY(144)
+STUB_ENTRY(145)
+STUB_ENTRY(146)
+STUB_ENTRY(147)
+STUB_ENTRY(148)
+STUB_ENTRY(149)
+STUB_ENTRY(150)
+STUB_ENTRY(151)
+STUB_ENTRY(152)
+STUB_ENTRY(153)
+STUB_ENTRY(154)
+STUB_ENTRY(155)
+STUB_ENTRY(156)
+STUB_ENTRY(157)
+STUB_ENTRY(158)
+STUB_ENTRY(159)
+STUB_ENTRY(160)
+STUB_ENTRY(161)
+STUB_ENTRY(162)
+STUB_ENTRY(163)
+STUB_ENTRY(164)
+STUB_ENTRY(165)
+STUB_ENTRY(166)
+STUB_ENTRY(167)
+STUB_ENTRY(168)
+STUB_ENTRY(169)
+STUB_ENTRY(170)
+STUB_ENTRY(171)
+STUB_ENTRY(172)
+STUB_ENTRY(173)
+STUB_ENTRY(174)
+STUB_ENTRY(175)
+STUB_ENTRY(176)
+STUB_ENTRY(177)
+STUB_ENTRY(178)
+STUB_ENTRY(179)
+STUB_ENTRY(180)
+STUB_ENTRY(181)
+STUB_ENTRY(182)
+STUB_ENTRY(183)
+STUB_ENTRY(184)
+STUB_ENTRY(185)
+STUB_ENTRY(186)
+STUB_ENTRY(187)
+STUB_ENTRY(188)
+STUB_ENTRY(189)
+STUB_ENTRY(190)
+STUB_ENTRY(191)
+STUB_ENTRY(192)
+STUB_ENTRY(193)
+STUB_ENTRY(194)
+STUB_ENTRY(195)
+STUB_ENTRY(196)
+STUB_ENTRY(197)
+STUB_ENTRY(198)
+STUB_ENTRY(199)
+STUB_ENTRY(200)
+STUB_ENTRY(201)
+STUB_ENTRY(202)
+STUB_ENTRY(203)
+STUB_ENTRY(204)
+STUB_ENTRY(205)
+STUB_ENTRY(206)
+STUB_ENTRY(207)
+STUB_ENTRY(208)
+STUB_ENTRY(209)
+STUB_ENTRY(210)
+STUB_ENTRY(211)
+STUB_ENTRY(212)
+STUB_ENTRY(213)
+STUB_ENTRY(214)
+STUB_ENTRY(215)
+STUB_ENTRY(216)
+STUB_ENTRY(217)
+STUB_ENTRY(218)
+STUB_ENTRY(219)
+STUB_ENTRY(220)
+STUB_ENTRY(221)
+STUB_ENTRY(222)
+STUB_ENTRY(223)
+STUB_ENTRY(224)
+STUB_ENTRY(225)
+STUB_ENTRY(226)
+STUB_ENTRY(227)
+STUB_ENTRY(228)
+STUB_ENTRY(229)
+STUB_ENTRY(230)
+STUB_ENTRY(231)
+STUB_ENTRY(232)
+STUB_ENTRY(233)
+STUB_ENTRY(234)
+STUB_ENTRY(235)
+STUB_ENTRY(236)
+STUB_ENTRY(237)
+STUB_ENTRY(238)
+STUB_ENTRY(239)
+STUB_ENTRY(240)
+STUB_ENTRY(241)
+STUB_ENTRY(242)
+STUB_ENTRY(243)
+STUB_ENTRY(244)
+STUB_ENTRY(245)
+STUB_ENTRY(246)
+STUB_ENTRY(247)
+STUB_ENTRY(248)
+STUB_ENTRY(249)
+SENTINEL_ENTRY(0)
+SENTINEL_ENTRY(1)
+SENTINEL_ENTRY(2)
+SENTINEL_ENTRY(3)
+SENTINEL_ENTRY(4)
diff --git a/xpcom/reflect/xptinfo/moz.build b/xpcom/reflect/xptinfo/moz.build
new file mode 100644
index 0000000000..9e4ce23258
--- /dev/null
+++ b/xpcom/reflect/xptinfo/moz.build
@@ -0,0 +1,21 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+UNIFIED_SOURCES += [
+ "xptinfo.cpp",
+]
+
+SOURCES += [
+ "!xptdata.cpp",
+]
+
+EXPORTS += [
+ "xptinfo.h",
+]
+
+include("/ipc/chromium/chromium-config.mozbuild")
+
+FINAL_LIBRARY = "xul"
diff --git a/xpcom/reflect/xptinfo/xptcodegen.py b/xpcom/reflect/xptinfo/xptcodegen.py
new file mode 100644
index 0000000000..d2859703b8
--- /dev/null
+++ b/xpcom/reflect/xptinfo/xptcodegen.py
@@ -0,0 +1,646 @@
+#!/usr/bin/env python
+# jsonlink.py - Merge JSON typelib files into a .cpp file
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import json
+from collections import OrderedDict
+
+import buildconfig
+from perfecthash import PerfectHash
+
+# Pick a nice power-of-two size for our intermediate PHF tables.
+PHFSIZE = 512
+
+
+def indented(s):
+ return s.replace("\n", "\n ")
+
+
+def cpp(v):
+ if type(v) == bool:
+ return "true" if v else "false"
+ return str(v)
+
+
+def mkstruct(*fields):
+ def mk(comment, **vals):
+ assert len(fields) == len(vals)
+ r = "{ // " + comment
+ r += indented(",".join("\n/* %s */ %s" % (k, cpp(vals[k])) for k in fields))
+ r += "\n}"
+ return r
+
+ return mk
+
+
+##########################################################
+# Ensure these fields are in the same order as xptinfo.h #
+##########################################################
+nsXPTInterfaceInfo = mkstruct(
+ "mIID",
+ "mName",
+ "mParent",
+ "mBuiltinClass",
+ "mMainProcessScriptableOnly",
+ "mMethods",
+ "mConsts",
+ "mFunction",
+ "mNumMethods",
+ "mNumConsts",
+)
+
+##########################################################
+# Ensure these fields are in the same order as xptinfo.h #
+##########################################################
+nsXPTType = mkstruct(
+ "mTag",
+ "mInParam",
+ "mOutParam",
+ "mOptionalParam",
+ "mData1",
+ "mData2",
+)
+
+##########################################################
+# Ensure these fields are in the same order as xptinfo.h #
+##########################################################
+nsXPTParamInfo = mkstruct(
+ "mType",
+)
+
+##########################################################
+# Ensure these fields are in the same order as xptinfo.h #
+##########################################################
+nsXPTMethodInfo = mkstruct(
+ "mName",
+ "mParams",
+ "mNumParams",
+ "mGetter",
+ "mSetter",
+ "mReflectable",
+ "mOptArgc",
+ "mContext",
+ "mHasRetval",
+ "mIsSymbol",
+)
+
+##########################################################
+# Ensure these fields are in the same order as xptinfo.h #
+##########################################################
+nsXPTDOMObjectInfo = mkstruct(
+ "mUnwrap",
+ "mWrap",
+ "mCleanup",
+)
+
+##########################################################
+# Ensure these fields are in the same order as xptinfo.h #
+##########################################################
+nsXPTConstantInfo = mkstruct(
+ "mName",
+ "mSigned",
+ "mValue",
+)
+
+
+# Helper functions for dealing with IIDs.
+#
+# Unfortunately, the way we represent IIDs in memory depends on the endianness
+# of the target architecture. We store an nsIID as a 16-byte, 4-tuple of:
+#
+# (uint32_t, uint16_t, uint16_t, [uint8_t; 8])
+#
+# Unfortunately, this means that when we hash the bytes of the nsIID on a
+# little-endian target system, we need to hash them in little-endian order.
+# These functions let us split the input hexadecimal string into components,
+# encoding each as a little-endian value, and producing an accurate bytearray.
+#
+# It would be nice to have a consistent representation of IIDs in memory such
+# that we don't have to do these gymnastics to get an accurate hash.
+
+
+def split_at_idxs(s, lengths):
+ idx = 0
+ for length in lengths:
+ yield s[idx : idx + length]
+ idx += length
+ assert idx == len(s)
+
+
+def split_iid(iid): # Get the individual components out of an IID string.
+ iid = iid.replace("-", "") # Strip any '-' delimiters
+ return tuple(split_at_idxs(iid, (8, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2)))
+
+
+def iid_bytes(iid): # Get the byte representation of the IID for hashing.
+ bs = bytearray()
+ for num in split_iid(iid):
+ b = bytearray.fromhex(num)
+ # Match endianness of the target platform for each component
+ if buildconfig.substs["TARGET_ENDIANNESS"] == "little":
+ b.reverse()
+ bs += b
+ return bs
+
+
+# Split a 16-bit integer into its high and low 8 bits
+def splitint(i):
+ assert i < 2**16
+ return (i >> 8, i & 0xFF)
+
+
+# Occasionally in xpconnect, we need to fabricate types to pass into the
+# conversion methods. In some cases, these types need to be arrays, which hold
+# indicies into the extra types array.
+#
+# These are some types which should have known indexes into the extra types
+# array.
+utility_types = [
+ {"tag": "TD_INT8"},
+ {"tag": "TD_UINT8"},
+ {"tag": "TD_INT16"},
+ {"tag": "TD_UINT16"},
+ {"tag": "TD_INT32"},
+ {"tag": "TD_UINT32"},
+ {"tag": "TD_INT64"},
+ {"tag": "TD_UINT64"},
+ {"tag": "TD_FLOAT"},
+ {"tag": "TD_DOUBLE"},
+ {"tag": "TD_BOOL"},
+ {"tag": "TD_CHAR"},
+ {"tag": "TD_WCHAR"},
+ {"tag": "TD_NSIDPTR"},
+ {"tag": "TD_PSTRING"},
+ {"tag": "TD_PWSTRING"},
+ {"tag": "TD_INTERFACE_IS_TYPE", "iid_is": 0},
+]
+
+
+# Core of the code generator. Takes a list of raw JSON XPT interfaces, and
+# writes out a file containing the necessary static declarations into fd.
+def link_to_cpp(interfaces, fd, header_fd):
+ # Perfect Hash from IID to interface.
+ iid_phf = PerfectHash(interfaces, PHFSIZE, key=lambda i: iid_bytes(i["uuid"]))
+ for idx, iface in enumerate(iid_phf.entries):
+ iface["idx"] = idx # Store the index in iid_phf of the entry.
+
+ # Perfect Hash from name to iid_phf index.
+ name_phf = PerfectHash(interfaces, PHFSIZE, key=lambda i: i["name"].encode("ascii"))
+
+ def interface_idx(name):
+ entry = name and name_phf.get_entry(name.encode("ascii"))
+ if entry:
+ return entry["idx"] + 1 # 1-based, use 0 as a sentinel.
+ return 0
+
+ # NOTE: State used while linking. This is done with closures rather than a
+ # class due to how this file's code evolved.
+ includes = set()
+ types = []
+ type_cache = {}
+ params = []
+ param_cache = {}
+ methods = []
+ max_params = 0
+ method_with_max_params = None
+ consts = []
+ domobjects = []
+ domobject_cache = {}
+ strings = OrderedDict()
+
+ def lower_uuid(uuid):
+ return (
+ "{0x%s, 0x%s, 0x%s, {0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s}}"
+ % split_iid(uuid)
+ )
+
+ def lower_domobject(do):
+ assert do["tag"] == "TD_DOMOBJECT"
+
+ idx = domobject_cache.get(do["name"])
+ if idx is None:
+ idx = domobject_cache[do["name"]] = len(domobjects)
+
+ includes.add(do["headerFile"])
+ domobjects.append(
+ nsXPTDOMObjectInfo(
+ "%d = %s" % (idx, do["name"]),
+ # These methods are defined at the top of the generated file.
+ mUnwrap="UnwrapDOMObject<mozilla::dom::prototypes::id::%s, %s>"
+ % (do["name"], do["native"]),
+ mWrap="WrapDOMObject<%s>" % do["native"],
+ mCleanup="CleanupDOMObject<%s>" % do["native"],
+ )
+ )
+
+ return idx
+
+ def lower_string(s):
+ if s in strings:
+ # We've already seen this string.
+ return strings[s]
+ elif len(strings):
+ # Get the last string we inserted (should be O(1) on OrderedDict).
+ last_s = next(reversed(strings))
+ strings[s] = strings[last_s] + len(last_s) + 1
+ else:
+ strings[s] = 0
+ return strings[s]
+
+ def lower_symbol(s):
+ return "uint32_t(JS::SymbolCode::%s)" % s
+
+ def lower_extra_type(type):
+ key = describe_type(type)
+ idx = type_cache.get(key)
+ if idx is None:
+ idx = type_cache[key] = len(types)
+ # Make sure `types` is the proper length for any recursive calls
+ # to `lower_extra_type` that might happen from within `lower_type`.
+ types.append(None)
+ realtype = lower_type(type)
+ types[idx] = realtype
+ return idx
+
+ def describe_type(type): # Create the type's documentation comment.
+ tag = type["tag"][3:].lower()
+ if tag == "legacy_array":
+ return "%s[size_is=%d]" % (describe_type(type["element"]), type["size_is"])
+ elif tag == "array":
+ return "Array<%s>" % describe_type(type["element"])
+ elif tag == "interface_type" or tag == "domobject":
+ return type["name"]
+ elif tag == "interface_is_type":
+ return "iid_is(%d)" % type["iid_is"]
+ elif tag.endswith("_size_is"):
+ return "%s(size_is=%d)" % (tag, type["size_is"])
+ return tag
+
+ def lower_type(type, in_=False, out=False, optional=False):
+ tag = type["tag"]
+ d1 = d2 = 0
+
+ # TD_VOID is used for types that can't be represented in JS, so they
+ # should not be represented in the XPT info.
+ assert tag != "TD_VOID"
+
+ if tag == "TD_LEGACY_ARRAY":
+ d1 = type["size_is"]
+ d2 = lower_extra_type(type["element"])
+
+ elif tag == "TD_ARRAY":
+ # NOTE: TD_ARRAY can hold 16 bits of type index, while
+ # TD_LEGACY_ARRAY can only hold 8.
+ d1, d2 = splitint(lower_extra_type(type["element"]))
+
+ elif tag == "TD_INTERFACE_TYPE":
+ d1, d2 = splitint(interface_idx(type["name"]))
+
+ elif tag == "TD_INTERFACE_IS_TYPE":
+ d1 = type["iid_is"]
+
+ elif tag == "TD_DOMOBJECT":
+ d1, d2 = splitint(lower_domobject(type))
+
+ elif tag.endswith("_SIZE_IS"):
+ d1 = type["size_is"]
+
+ assert d1 < 256 and d2 < 256, "Data values too large"
+ return nsXPTType(
+ describe_type(type),
+ mTag=tag,
+ mData1=d1,
+ mData2=d2,
+ mInParam=in_,
+ mOutParam=out,
+ mOptionalParam=optional,
+ )
+
+ def lower_param(param, paramname):
+ params.append(
+ nsXPTParamInfo(
+ "%d = %s" % (len(params), paramname),
+ mType=lower_type(
+ param["type"],
+ in_="in" in param["flags"],
+ out="out" in param["flags"],
+ optional="optional" in param["flags"],
+ ),
+ )
+ )
+
+ def is_type_reflectable(type):
+ # All native types end up getting tagged as void*, or as wrapper types around void*
+ if type["tag"] == "TD_VOID":
+ return False
+ if type["tag"] in ("TD_ARRAY", "TD_LEGACY_ARRAY"):
+ return is_type_reflectable(type["element"])
+ return True
+
+ def is_method_reflectable(method):
+ if "hidden" in method["flags"]:
+ return False
+
+ for param in method["params"]:
+ # Reflected methods can't use non-reflectable types.
+ if not is_type_reflectable(param["type"]):
+ return False
+
+ return True
+
+ def lower_method(method, ifacename):
+ methodname = "%s::%s" % (ifacename, method["name"])
+
+ isSymbol = "symbol" in method["flags"]
+ reflectable = is_method_reflectable(method)
+
+ if not reflectable:
+ # Hide the parameters of methods that can't be called from JS to
+ # reduce the size of the file.
+ paramidx = name = numparams = 0
+ else:
+ if isSymbol:
+ name = lower_symbol(method["name"])
+ else:
+ name = lower_string(method["name"])
+
+ numparams = len(method["params"])
+
+ # Check cache for parameters
+ cachekey = json.dumps(method["params"], sort_keys=True)
+ paramidx = param_cache.get(cachekey)
+ if paramidx is None:
+ paramidx = param_cache[cachekey] = len(params)
+ for idx, param in enumerate(method["params"]):
+ lower_param(param, "%s[%d]" % (methodname, idx))
+
+ nonlocal max_params, method_with_max_params
+ if numparams > max_params:
+ max_params = numparams
+ method_with_max_params = methodname
+ methods.append(
+ nsXPTMethodInfo(
+ "%d = %s" % (len(methods), methodname),
+ mName=name,
+ mParams=paramidx,
+ mNumParams=numparams,
+ # Flags
+ mGetter="getter" in method["flags"],
+ mSetter="setter" in method["flags"],
+ mReflectable=reflectable,
+ mOptArgc="optargc" in method["flags"],
+ mContext="jscontext" in method["flags"],
+ mHasRetval="hasretval" in method["flags"],
+ mIsSymbol=isSymbol,
+ )
+ )
+
+ def lower_const(const, ifacename):
+ assert const["type"]["tag"] in [
+ "TD_INT16",
+ "TD_INT32",
+ "TD_UINT8",
+ "TD_UINT16",
+ "TD_UINT32",
+ ]
+ is_signed = const["type"]["tag"] in ["TD_INT16", "TD_INT32"]
+
+ # Constants are always either signed or unsigned 16 or 32 bit integers,
+ # which we will only need to convert to JS values. To save on space,
+ # don't bother storing the type, and instead just store a 32-bit
+ # unsigned integer, and stash whether to interpret it as signed.
+ consts.append(
+ nsXPTConstantInfo(
+ "%d = %s::%s" % (len(consts), ifacename, const["name"]),
+ mName=lower_string(const["name"]),
+ mSigned=is_signed,
+ mValue="(uint32_t)%d" % const["value"],
+ )
+ )
+
+ def ancestors(iface):
+ yield iface
+ while iface["parent"]:
+ iface = name_phf.get_entry(iface["parent"].encode("ascii"))
+ yield iface
+
+ def lower_iface(iface):
+ method_cnt = sum(len(i["methods"]) for i in ancestors(iface))
+ const_cnt = sum(len(i["consts"]) for i in ancestors(iface))
+
+ # The number of maximum methods is not arbitrary. It is the same value
+ # as in xpcom/reflect/xptcall/genstubs.pl; do not change this value
+ # without changing that one or you WILL see problems.
+ #
+ # In addition, mNumMethods and mNumConsts are stored as a 8-bit ints,
+ # meaning we cannot exceed 255 methods/consts on any interface.
+ assert method_cnt < 250, "%s has too many methods" % iface["name"]
+ assert const_cnt < 256, "%s has too many constants" % iface["name"]
+
+ # Store the lowered interface as 'cxx' on the iface object.
+ iface["cxx"] = nsXPTInterfaceInfo(
+ "%d = %s" % (iface["idx"], iface["name"]),
+ mIID=lower_uuid(iface["uuid"]),
+ mName=lower_string(iface["name"]),
+ mParent=interface_idx(iface["parent"]),
+ mMethods=len(methods),
+ mNumMethods=method_cnt,
+ mConsts=len(consts),
+ mNumConsts=const_cnt,
+ # Flags
+ mBuiltinClass="builtinclass" in iface["flags"],
+ mMainProcessScriptableOnly="main_process_only" in iface["flags"],
+ mFunction="function" in iface["flags"],
+ )
+
+ # Lower methods and constants used by this interface
+ for method in iface["methods"]:
+ lower_method(method, iface["name"])
+ for const in iface["consts"]:
+ lower_const(const, iface["name"])
+
+ # Lower the types which have fixed indexes first, and check that the indexes
+ # seem correct.
+ for expected, ty in enumerate(utility_types):
+ got = lower_extra_type(ty)
+ assert got == expected, "Wrong index when lowering"
+
+ # Lower interfaces in the order of the IID phf's entries lookup.
+ for iface in iid_phf.entries:
+ lower_iface(iface)
+
+ # Write out the final output files
+ fd.write("/* THIS FILE WAS GENERATED BY xptcodegen.py - DO NOT EDIT */\n\n")
+ header_fd.write("/* THIS FILE WAS GENERATED BY xptcodegen.py - DO NOT EDIT */\n\n")
+
+ header_fd.write(
+ """
+#ifndef xptdata_h
+#define xptdata_h
+
+enum class nsXPTInterface : uint16_t {
+"""
+ )
+
+ for entry in iid_phf.entries:
+ header_fd.write(" %s,\n" % entry["name"])
+
+ header_fd.write(
+ """
+};
+
+#endif
+"""
+ )
+
+ # Include any bindings files which we need to include for webidl types
+ for include in sorted(includes):
+ fd.write('#include "%s"\n' % include)
+
+ # Write out our header
+ fd.write(
+ """
+#include "xptinfo.h"
+#include "mozilla/PerfectHash.h"
+#include "mozilla/dom/BindingUtils.h"
+
+// These template methods are specialized to be used in the sDOMObjects table.
+template<mozilla::dom::prototypes::ID PrototypeID, typename T>
+static nsresult UnwrapDOMObject(JS::Handle<JS::Value> aHandle, void** aObj, JSContext* aCx)
+{
+ RefPtr<T> p;
+ nsresult rv = mozilla::dom::UnwrapObject<PrototypeID, T>(aHandle, p, aCx);
+ p.forget(aObj);
+ return rv;
+}
+
+template<typename T>
+static bool WrapDOMObject(JSContext* aCx, void* aObj, JS::MutableHandle<JS::Value> aHandle)
+{
+ return mozilla::dom::GetOrCreateDOMReflector(aCx, reinterpret_cast<T*>(aObj), aHandle);
+}
+
+template<typename T>
+static void CleanupDOMObject(void* aObj)
+{
+ RefPtr<T> p = already_AddRefed<T>(reinterpret_cast<T*>(aObj));
+}
+
+namespace xpt {
+namespace detail {
+
+"""
+ )
+
+ # Static data arrays
+ def array(ty, name, els):
+ fd.write(
+ "const %s %s[] = {%s\n};\n\n"
+ % (ty, name, ",".join(indented("\n" + str(e)) for e in els))
+ )
+
+ array("nsXPTType", "sTypes", types)
+ array("nsXPTParamInfo", "sParams", params)
+ array("nsXPTMethodInfo", "sMethods", methods)
+ # Verify that stack-allocated buffers will do for xptcall implementations.
+ msg = (
+ "Too many method arguments in %s. "
+ "Either reduce the number of arguments "
+ "or increase PARAM_BUFFER_COUNT." % method_with_max_params
+ )
+ fd.write('static_assert(%s <= PARAM_BUFFER_COUNT, "%s");\n\n' % (max_params, msg))
+ array("nsXPTDOMObjectInfo", "sDOMObjects", domobjects)
+ array("nsXPTConstantInfo", "sConsts", consts)
+
+ # The strings array. We write out individual characters to avoid MSVC restrictions.
+ fd.write("const char sStrings[] = {\n")
+ for s, off in strings.items():
+ fd.write(" // %d = %s\n '%s','\\0',\n" % (off, s, "','".join(s)))
+ fd.write("};\n\n")
+
+ # Build the perfect hash table for InterfaceByIID
+ fd.write(
+ iid_phf.cxx_codegen(
+ name="InterfaceByIID",
+ entry_type="nsXPTInterfaceInfo",
+ entries_name="sInterfaces",
+ lower_entry=lambda iface: iface["cxx"],
+ # Check that the IIDs match to support IID keys not in the map.
+ return_type="const nsXPTInterfaceInfo*",
+ return_entry="return entry.IID().Equals(aKey) ? &entry : nullptr;",
+ key_type="const nsIID&",
+ key_bytes="reinterpret_cast<const char*>(&aKey)",
+ key_length="sizeof(nsIID)",
+ )
+ )
+ fd.write("\n")
+
+ # Build the perfect hash table for InterfaceByName
+ fd.write(
+ name_phf.cxx_codegen(
+ name="InterfaceByName",
+ entry_type="uint16_t",
+ lower_entry=lambda iface: "%-4d /* %s */" % (iface["idx"], iface["name"]),
+ # Get the actual nsXPTInterfaceInfo from sInterfaces, and
+ # double-check that names match.
+ return_type="const nsXPTInterfaceInfo*",
+ return_entry="return strcmp(sInterfaces[entry].Name(), aKey) == 0"
+ " ? &sInterfaces[entry] : nullptr;",
+ )
+ )
+ fd.write("\n")
+
+ # Generate some checks that the indexes for the utility types match the
+ # declared ones in xptinfo.h
+ for idx, ty in enumerate(utility_types):
+ fd.write(
+ 'static_assert(%d == (uint8_t)nsXPTType::Idx::%s, "Bad idx");\n'
+ % (idx, ty["tag"][3:])
+ )
+
+ fd.write(
+ """
+const uint16_t sInterfacesSize = mozilla::ArrayLength(sInterfaces);
+
+} // namespace detail
+} // namespace xpt
+"""
+ )
+
+
+def link_and_write(files, outfile, outheader):
+ interfaces = []
+ for file in files:
+ with open(file, "r") as fd:
+ interfaces += json.load(fd)
+
+ iids = set()
+ names = set()
+ for interface in interfaces:
+ assert interface["uuid"] not in iids, "duplicated UUID %s" % interface["uuid"]
+ assert interface["name"] not in names, "duplicated name %s" % interface["name"]
+ iids.add(interface["uuid"])
+ names.add(interface["name"])
+
+ link_to_cpp(interfaces, outfile, outheader)
+
+
+def main():
+ import sys
+ from argparse import ArgumentParser
+
+ parser = ArgumentParser()
+ parser.add_argument("outfile", help="Output C++ file to generate")
+ parser.add_argument("outheader", help="Output C++ header file to generate")
+ parser.add_argument("xpts", nargs="*", help="source xpt files")
+
+ args = parser.parse_args(sys.argv[1:])
+ with open(args.outfile, "w") as fd, open(args.outheader, "w") as header_fd:
+ link_and_write(args.xpts, fd, header_fd)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/xpcom/reflect/xptinfo/xptinfo.cpp b/xpcom/reflect/xptinfo/xptinfo.cpp
new file mode 100644
index 0000000000..c44e97cad4
--- /dev/null
+++ b/xpcom/reflect/xptinfo/xptinfo.cpp
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+#include "xptinfo.h"
+#include "nsISupports.h"
+#include "mozilla/dom/DOMJSClass.h"
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/ArrayUtils.h"
+
+#include "jsfriendapi.h"
+#include "js/Symbol.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+using namespace xpt::detail;
+
+////////////////////////////////////
+// Constant Lookup Helper Methods //
+////////////////////////////////////
+
+bool nsXPTInterfaceInfo::HasAncestor(const nsIID& aIID) const {
+ for (const auto* info = this; info; info = info->GetParent()) {
+ if (info->IID() == aIID) {
+ return true;
+ }
+ }
+ return false;
+}
+
+const nsXPTConstantInfo& nsXPTInterfaceInfo::Constant(uint16_t aIndex) const {
+ MOZ_ASSERT(aIndex < ConstantCount());
+
+ if (const nsXPTInterfaceInfo* pi = GetParent()) {
+ if (aIndex < pi->ConstantCount()) {
+ return pi->Constant(aIndex);
+ }
+ aIndex -= pi->ConstantCount();
+ }
+
+ return xpt::detail::GetConstant(mConsts + aIndex);
+}
+
+const nsXPTMethodInfo& nsXPTInterfaceInfo::Method(uint16_t aIndex) const {
+ MOZ_ASSERT(aIndex < MethodCount());
+
+ if (const nsXPTInterfaceInfo* pi = GetParent()) {
+ if (aIndex < pi->MethodCount()) {
+ return pi->Method(aIndex);
+ }
+ aIndex -= pi->MethodCount();
+ }
+
+ return xpt::detail::GetMethod(mMethods + aIndex);
+}
+
+nsresult nsXPTInterfaceInfo::GetMethodInfo(
+ uint16_t aIndex, const nsXPTMethodInfo** aInfo) const {
+ *aInfo = aIndex < MethodCount() ? &Method(aIndex) : nullptr;
+ return *aInfo ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult nsXPTInterfaceInfo::GetConstant(uint16_t aIndex,
+ JS::MutableHandle<JS::Value> aConstant,
+ char** aName) const {
+ if (aIndex < ConstantCount()) {
+ aConstant.set(Constant(aIndex).JSValue());
+ *aName = moz_xstrdup(Constant(aIndex).Name());
+ return NS_OK;
+ }
+ return NS_ERROR_FAILURE;
+}
+
+////////////////////////////////////
+// nsXPTMethodInfo symbol helpers //
+////////////////////////////////////
+
+const char* nsXPTMethodInfo::SymbolDescription() const {
+ switch (GetSymbolCode()) {
+#define XPC_WELL_KNOWN_SYMBOL_DESCR_CASE(name) \
+ case JS::SymbolCode::name: \
+ return #name;
+ JS_FOR_EACH_WELL_KNOWN_SYMBOL(XPC_WELL_KNOWN_SYMBOL_DESCR_CASE)
+#undef XPC_WELL_KNOWN_SYMBOL_DESCR_CASE
+
+ default:
+ return "";
+ }
+}
+
+bool nsXPTMethodInfo::GetId(JSContext* aCx, jsid& aId) const {
+ if (IsSymbol()) {
+ aId = JS::PropertyKey::Symbol(GetSymbol(aCx));
+ return true;
+ }
+
+ JSString* str = JS_AtomizeString(aCx, Name());
+ if (!str) {
+ return false;
+ }
+ aId = JS::PropertyKey::NonIntAtom(str);
+ return true;
+}
diff --git a/xpcom/reflect/xptinfo/xptinfo.h b/xpcom/reflect/xptinfo/xptinfo.h
new file mode 100644
index 0000000000..2456c2c2b5
--- /dev/null
+++ b/xpcom/reflect/xptinfo/xptinfo.h
@@ -0,0 +1,711 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+/**
+ * Structures and methods with information about XPCOM interfaces for use by
+ * XPConnect. The static backing data structures used by this file are generated
+ * from xpidl interfaces by the jsonxpt.py and xptcodegen.py scripts.
+ */
+
+#ifndef xptinfo_h
+#define xptinfo_h
+
+#include <stdint.h>
+#include "nsID.h"
+#include "mozilla/Assertions.h"
+#include "jsapi.h"
+#include "js/Symbol.h"
+#include "js/Value.h"
+#include "nsString.h"
+#include "nsTArray.h"
+
+// Forward Declarations
+namespace mozilla {
+namespace dom {
+struct NativePropertyHooks;
+} // namespace dom
+} // namespace mozilla
+
+struct nsXPTInterfaceInfo;
+struct nsXPTType;
+struct nsXPTParamInfo;
+struct nsXPTMethodInfo;
+struct nsXPTConstantInfo;
+struct nsXPTDOMObjectInfo;
+
+enum class nsXPTInterface : uint16_t;
+
+// Internal helper methods.
+namespace xpt {
+namespace detail {
+
+inline const nsXPTInterfaceInfo* GetInterface(uint16_t aIndex);
+inline const nsXPTType& GetType(uint16_t aIndex);
+inline const nsXPTParamInfo& GetParam(uint16_t aIndex);
+inline const nsXPTMethodInfo& GetMethod(uint16_t aIndex);
+inline const nsXPTConstantInfo& GetConstant(uint16_t aIndex);
+inline const nsXPTDOMObjectInfo& GetDOMObjectInfo(uint16_t aIndex);
+inline const char* GetString(uint32_t aIndex);
+
+const nsXPTInterfaceInfo* InterfaceByIID(const nsIID& aIID);
+const nsXPTInterfaceInfo* InterfaceByName(const char* aName);
+
+extern const uint16_t sInterfacesSize;
+
+} // namespace detail
+} // namespace xpt
+
+/*
+ * An Interface describes a single XPCOM interface, including all of its
+ * methods. We don't record non-scriptable interfaces.
+ */
+struct nsXPTInterfaceInfo {
+ // High efficiency getters for Interfaces based on perfect hashes.
+ static const nsXPTInterfaceInfo* ByIID(const nsIID& aIID) {
+ return xpt::detail::InterfaceByIID(aIID);
+ }
+ static const nsXPTInterfaceInfo* ByName(const char* aName) {
+ return xpt::detail::InterfaceByName(aName);
+ }
+
+ static const nsXPTInterfaceInfo* Get(nsXPTInterface aID) {
+ return ByIndex(uint16_t(aID));
+ }
+
+ // These are only needed for Components_interfaces's enumerator.
+ static const nsXPTInterfaceInfo* ByIndex(uint16_t aIndex) {
+ // NOTE: We add 1 here, as the internal index 0 is reserved for null.
+ return xpt::detail::GetInterface(aIndex + 1);
+ }
+ static uint16_t InterfaceCount() { return xpt::detail::sInterfacesSize; }
+
+ // Interface flag getters
+ bool IsFunction() const { return mFunction; }
+ bool IsBuiltinClass() const { return mBuiltinClass; }
+ bool IsMainProcessScriptableOnly() const {
+ return mMainProcessScriptableOnly;
+ }
+
+ const char* Name() const { return xpt::detail::GetString(mName); }
+ const nsIID& IID() const { return mIID; }
+
+ // Get the parent interface, or null if this interface doesn't have a parent.
+ const nsXPTInterfaceInfo* GetParent() const {
+ return xpt::detail::GetInterface(mParent);
+ }
+
+ // Do we have an ancestor interface with the given IID?
+ bool HasAncestor(const nsIID& aIID) const;
+
+ // Get methods & constants
+ uint16_t ConstantCount() const { return mNumConsts; }
+ const nsXPTConstantInfo& Constant(uint16_t aIndex) const;
+ uint16_t MethodCount() const { return mNumMethods; }
+ const nsXPTMethodInfo& Method(uint16_t aIndex) const;
+
+ nsresult GetMethodInfo(uint16_t aIndex, const nsXPTMethodInfo** aInfo) const;
+ nsresult GetConstant(uint16_t aIndex, JS::MutableHandle<JS::Value> constant,
+ char** aName) const;
+
+ ////////////////////////////////////////////////////////////////
+ // Ensure these fields are in the same order as xptcodegen.py //
+ ////////////////////////////////////////////////////////////////
+
+ nsID mIID;
+ uint32_t mName; // Index into xpt::detail::sStrings
+
+ uint16_t mParent : 14;
+ uint16_t mBuiltinClass : 1;
+ // XXX(nika): Do we need this if we don't have addons anymore?
+ uint16_t mMainProcessScriptableOnly : 1;
+
+ uint16_t mMethods; // Index into xpt::detail::sMethods
+
+ uint16_t mConsts : 14; // Index into xpt::detail::sConsts
+ uint16_t mFunction : 1;
+ // uint16_t unused : 1;
+
+ uint8_t mNumMethods; // NOTE(24/04/18): largest=nsIDocShell (193)
+ uint8_t mNumConsts; // NOTE(24/04/18): largest=nsIAccessibleRole (175)
+};
+
+// The fields in nsXPTInterfaceInfo were carefully ordered to minimize size.
+static_assert(sizeof(nsXPTInterfaceInfo) == 28, "wrong size?");
+
+/*
+ * The following enum represents contains the different tag types which
+ * can be found in nsXPTTypeInfo::mTag.
+ *
+ * WARNING: mTag is 5 bits wide, supporting at most 32 tags.
+ */
+enum nsXPTTypeTag : uint8_t {
+ // Arithmetic (POD) Types
+ // - Do not require cleanup,
+ // - All bit patterns are valid,
+ // - Outparams may be uninitialized by caller,
+ // - Directly supported in xptcall.
+ //
+ // NOTE: The name 'Arithmetic' comes from Harbison/Steele. Despite being a tad
+ // unclear, it is used frequently in xptcall, so is unlikely to be changed.
+ TD_INT8 = 0,
+ TD_INT16 = 1,
+ TD_INT32 = 2,
+ TD_INT64 = 3,
+ TD_UINT8 = 4,
+ TD_UINT16 = 5,
+ TD_UINT32 = 6,
+ TD_UINT64 = 7,
+ TD_FLOAT = 8,
+ TD_DOUBLE = 9,
+ TD_BOOL = 10,
+ TD_CHAR = 11,
+ TD_WCHAR = 12,
+ _TD_LAST_ARITHMETIC = TD_WCHAR,
+
+ // Pointer Types
+ // - Require cleanup unless NULL,
+ // - All-zeros (NULL) bit pattern is valid,
+ // - Outparams may be uninitialized by caller,
+ // - Supported in xptcall as raw pointer.
+ TD_VOID = 13,
+ TD_NSIDPTR = 14,
+ TD_PSTRING = 15,
+ TD_PWSTRING = 16,
+ TD_INTERFACE_TYPE = 17,
+ TD_INTERFACE_IS_TYPE = 18,
+ TD_LEGACY_ARRAY = 19,
+ TD_PSTRING_SIZE_IS = 20,
+ TD_PWSTRING_SIZE_IS = 21,
+ TD_DOMOBJECT = 22,
+ TD_PROMISE = 23,
+ _TD_LAST_POINTER = TD_PROMISE,
+
+ // Complex Types
+ // - Require cleanup,
+ // - Always passed indirectly,
+ // - Outparams must be initialized by caller,
+ // - Supported in xptcall due to indirection.
+ TD_UTF8STRING = 24,
+ TD_CSTRING = 25,
+ TD_ASTRING = 26,
+ TD_NSID = 27,
+ TD_JSVAL = 28,
+ TD_ARRAY = 29,
+ _TD_LAST_COMPLEX = TD_ARRAY
+};
+
+static_assert(_TD_LAST_COMPLEX < 32, "nsXPTTypeTag must fit in 5 bits");
+
+/*
+ * A nsXPTType is a union used to identify the type of a method argument or
+ * return value. The internal data is stored as an 5-bit tag, and two 8-bit
+ * integers, to keep alignment requirements low.
+ *
+ * nsXPTType contains 3 extra bits, reserved for use by nsXPTParamInfo.
+ */
+struct nsXPTType {
+ nsXPTTypeTag Tag() const { return static_cast<nsXPTTypeTag>(mTag); }
+
+ // The index in the function argument list which should be used when
+ // determining the iid_is or size_is properties of this dependent type.
+ uint8_t ArgNum() const {
+ MOZ_ASSERT(Tag() == TD_INTERFACE_IS_TYPE || Tag() == TD_PSTRING_SIZE_IS ||
+ Tag() == TD_PWSTRING_SIZE_IS || Tag() == TD_LEGACY_ARRAY);
+ return mData1;
+ }
+
+ private:
+ // Helper for reading 16-bit data values split between mData1 and mData2.
+ uint16_t Data16() const {
+ return static_cast<uint16_t>(mData1 << 8) | mData2;
+ }
+
+ public:
+ // Get the type of the element in the current array or sequence. Arrays only
+ // fit 8 bits of type data, while sequences support up to 16 bits of type data
+ // due to not needing to store an ArgNum.
+ const nsXPTType& ArrayElementType() const {
+ if (Tag() == TD_LEGACY_ARRAY) {
+ return xpt::detail::GetType(mData2);
+ }
+ MOZ_ASSERT(Tag() == TD_ARRAY);
+ return xpt::detail::GetType(Data16());
+ }
+
+ // We store the 16-bit iface value as two 8-bit values in order to
+ // avoid 16-bit alignment requirements for XPTTypeDescriptor, which
+ // reduces its size and also the size of XPTParamDescriptor.
+ const nsXPTInterfaceInfo* GetInterface() const {
+ MOZ_ASSERT(Tag() == TD_INTERFACE_TYPE);
+ return xpt::detail::GetInterface(Data16());
+ }
+
+ const nsXPTDOMObjectInfo& GetDOMObjectInfo() const {
+ MOZ_ASSERT(Tag() == TD_DOMOBJECT);
+ return xpt::detail::GetDOMObjectInfo(Data16());
+ }
+
+ // See the comments in nsXPTTypeTag for an explanation as to what each of
+ // these categories mean.
+ bool IsArithmetic() const { return Tag() <= _TD_LAST_ARITHMETIC; }
+ bool IsPointer() const {
+ return !IsArithmetic() && Tag() <= _TD_LAST_POINTER;
+ }
+ bool IsComplex() const { return Tag() > _TD_LAST_POINTER; }
+
+ bool IsInterfacePointer() const {
+ return Tag() == TD_INTERFACE_TYPE || Tag() == TD_INTERFACE_IS_TYPE;
+ }
+
+ bool IsDependent() const {
+ return (Tag() == TD_ARRAY && InnermostType().IsDependent()) ||
+ Tag() == TD_INTERFACE_IS_TYPE || Tag() == TD_LEGACY_ARRAY ||
+ Tag() == TD_PSTRING_SIZE_IS || Tag() == TD_PWSTRING_SIZE_IS;
+ }
+
+ // Unwrap a nested type to its innermost value (e.g. through arrays).
+ const nsXPTType& InnermostType() const {
+ if (Tag() == TD_LEGACY_ARRAY || Tag() == TD_ARRAY) {
+ return ArrayElementType().InnermostType();
+ }
+ return *this;
+ }
+
+ // In-memory size of native type in bytes.
+ inline size_t Stride() const;
+
+ // Offset the given base pointer to reference the element at the given index.
+ void* ElementPtr(const void* aBase, uint32_t aIndex) const {
+ return (char*)aBase + (aIndex * Stride());
+ }
+
+ // Zero out a native value of the given type. The type must not be 'complex'.
+ void ZeroValue(void* aValue) const {
+ MOZ_RELEASE_ASSERT(!IsComplex(), "Cannot zero a complex value");
+ memset(aValue, 0, Stride());
+ }
+
+ // Indexes into the extra types array of a small set of known types.
+ enum class Idx : uint8_t {
+ INT8 = 0,
+ UINT8,
+ INT16,
+ UINT16,
+ INT32,
+ UINT32,
+ INT64,
+ UINT64,
+ FLOAT,
+ DOUBLE,
+ BOOL,
+ CHAR,
+ WCHAR,
+ NSIDPTR,
+ PSTRING,
+ PWSTRING,
+ INTERFACE_IS_TYPE
+ };
+
+ // Helper methods for fabricating nsXPTType values used by xpconnect.
+ static nsXPTType MkArrayType(Idx aInner) {
+ MOZ_ASSERT(aInner <= Idx::INTERFACE_IS_TYPE);
+ return {TD_LEGACY_ARRAY, false, false, false, 0, (uint8_t)aInner};
+ }
+ static const nsXPTType& Get(Idx aInner) {
+ MOZ_ASSERT(aInner <= Idx::INTERFACE_IS_TYPE);
+ return xpt::detail::GetType((uint8_t)aInner);
+ }
+
+ ///////////////////////////////////////
+ // nsXPTType backwards compatibility //
+ ///////////////////////////////////////
+
+ nsXPTType& operator=(nsXPTTypeTag aPrefix) {
+ mTag = aPrefix;
+ return *this;
+ }
+ operator nsXPTTypeTag() const { return Tag(); }
+
+#define TD_ALIAS_(name_, value_) static constexpr nsXPTTypeTag name_ = value_
+ TD_ALIAS_(T_I8, TD_INT8);
+ TD_ALIAS_(T_I16, TD_INT16);
+ TD_ALIAS_(T_I32, TD_INT32);
+ TD_ALIAS_(T_I64, TD_INT64);
+ TD_ALIAS_(T_U8, TD_UINT8);
+ TD_ALIAS_(T_U16, TD_UINT16);
+ TD_ALIAS_(T_U32, TD_UINT32);
+ TD_ALIAS_(T_U64, TD_UINT64);
+ TD_ALIAS_(T_FLOAT, TD_FLOAT);
+ TD_ALIAS_(T_DOUBLE, TD_DOUBLE);
+ TD_ALIAS_(T_BOOL, TD_BOOL);
+ TD_ALIAS_(T_CHAR, TD_CHAR);
+ TD_ALIAS_(T_WCHAR, TD_WCHAR);
+ TD_ALIAS_(T_VOID, TD_VOID);
+ TD_ALIAS_(T_NSIDPTR, TD_NSIDPTR);
+ TD_ALIAS_(T_CHAR_STR, TD_PSTRING);
+ TD_ALIAS_(T_WCHAR_STR, TD_PWSTRING);
+ TD_ALIAS_(T_INTERFACE, TD_INTERFACE_TYPE);
+ TD_ALIAS_(T_INTERFACE_IS, TD_INTERFACE_IS_TYPE);
+ TD_ALIAS_(T_LEGACY_ARRAY, TD_LEGACY_ARRAY);
+ TD_ALIAS_(T_PSTRING_SIZE_IS, TD_PSTRING_SIZE_IS);
+ TD_ALIAS_(T_PWSTRING_SIZE_IS, TD_PWSTRING_SIZE_IS);
+ TD_ALIAS_(T_UTF8STRING, TD_UTF8STRING);
+ TD_ALIAS_(T_CSTRING, TD_CSTRING);
+ TD_ALIAS_(T_ASTRING, TD_ASTRING);
+ TD_ALIAS_(T_NSID, TD_NSID);
+ TD_ALIAS_(T_JSVAL, TD_JSVAL);
+ TD_ALIAS_(T_DOMOBJECT, TD_DOMOBJECT);
+ TD_ALIAS_(T_PROMISE, TD_PROMISE);
+ TD_ALIAS_(T_ARRAY, TD_ARRAY);
+#undef TD_ALIAS_
+
+ ////////////////////////////////////////////////////////////////
+ // Ensure these fields are in the same order as xptcodegen.py //
+ ////////////////////////////////////////////////////////////////
+
+ uint8_t mTag : 5;
+
+ // Parameter bitflags are packed into the XPTTypeDescriptor to save space.
+ // When the TypeDescriptor is not in a parameter, these flags are ignored.
+ uint8_t mInParam : 1;
+ uint8_t mOutParam : 1;
+ uint8_t mOptionalParam : 1;
+
+ // The data for the different variants is stored in these two data fields.
+ // These should only be accessed via the getter methods above, which will
+ // assert if the tag is invalid.
+ uint8_t mData1;
+ uint8_t mData2;
+};
+
+// The fields in nsXPTType were carefully ordered to minimize size.
+static_assert(sizeof(nsXPTType) == 3, "wrong size");
+
+/*
+ * A nsXPTParamInfo is used to describe either a single argument to a method or
+ * a method's result. It stores its flags in the type descriptor to save space.
+ */
+struct nsXPTParamInfo {
+ bool IsIn() const { return mType.mInParam; }
+ bool IsOut() const { return mType.mOutParam; }
+ bool IsOptional() const { return mType.mOptionalParam; }
+ bool IsShared() const { return false; } // XXX remove (backcompat)
+
+ // Get the type of this parameter.
+ const nsXPTType& Type() const { return mType; }
+ const nsXPTType& GetType() const {
+ return Type();
+ } // XXX remove (backcompat)
+
+ // Whether this parameter is passed indirectly on the stack. All out/inout
+ // params are passed indirectly, and complex types are always passed
+ // indirectly.
+ bool IsIndirect() const { return IsOut() || Type().IsComplex(); }
+
+ ////////////////////////////////////////////////////////////////
+ // Ensure these fields are in the same order as xptcodegen.py //
+ ////////////////////////////////////////////////////////////////
+
+ nsXPTType mType;
+};
+
+// The fields in nsXPTParamInfo were carefully ordered to minimize size.
+static_assert(sizeof(nsXPTParamInfo) == 3, "wrong size");
+
+/*
+ * A nsXPTMethodInfo is used to describe a single interface method.
+ */
+struct nsXPTMethodInfo {
+ bool IsGetter() const { return mGetter; }
+ bool IsSetter() const { return mSetter; }
+ bool IsReflectable() const { return mReflectable; }
+ bool IsSymbol() const { return mIsSymbol; }
+ bool WantsOptArgc() const { return mOptArgc; }
+ bool WantsContext() const { return mContext; }
+ uint8_t ParamCount() const { return mNumParams; }
+
+ const char* Name() const {
+ MOZ_ASSERT(!IsSymbol());
+ return xpt::detail::GetString(mName);
+ }
+ const nsXPTParamInfo& Param(uint8_t aIndex) const {
+ MOZ_ASSERT(aIndex < mNumParams);
+ return xpt::detail::GetParam(mParams + aIndex);
+ }
+
+ bool HasRetval() const { return mHasRetval; }
+ const nsXPTParamInfo* GetRetval() const {
+ return mHasRetval ? &Param(mNumParams - 1) : nullptr;
+ }
+
+ // If this is an [implicit_jscontext] method, returns the index of the
+ // implicit JSContext* argument in the C++ method's argument list.
+ // Otherwise returns UINT8_MAX.
+ uint8_t IndexOfJSContext() const {
+ if (!WantsContext()) {
+ return UINT8_MAX;
+ }
+ if (IsGetter() || IsSetter()) {
+ // Getters/setters always have the context as first argument.
+ return 0;
+ }
+ // The context comes before the return value, if there is one.
+ MOZ_ASSERT_IF(HasRetval(), ParamCount() > 0);
+ return ParamCount() - uint8_t(HasRetval());
+ }
+
+ JS::SymbolCode GetSymbolCode() const {
+ MOZ_ASSERT(IsSymbol());
+ return JS::SymbolCode(mName);
+ }
+
+ JS::Symbol* GetSymbol(JSContext* aCx) const {
+ return JS::GetWellKnownSymbol(aCx, GetSymbolCode());
+ }
+
+ const char* SymbolDescription() const;
+
+ const char* NameOrDescription() const {
+ if (IsSymbol()) {
+ return SymbolDescription();
+ }
+ return Name();
+ }
+
+ bool GetId(JSContext* aCx, jsid& aId) const;
+
+ /////////////////////////////////////////////
+ // nsXPTMethodInfo backwards compatibility //
+ /////////////////////////////////////////////
+
+ const char* GetName() const { return Name(); }
+
+ uint8_t GetParamCount() const { return ParamCount(); }
+ const nsXPTParamInfo& GetParam(uint8_t aIndex) const { return Param(aIndex); }
+
+ ////////////////////////////////////////////////////////////////
+ // Ensure these fields are in the same order as xptcodegen.py //
+ ////////////////////////////////////////////////////////////////
+
+ uint32_t mName; // Index into xpt::detail::sStrings.
+ uint16_t mParams; // Index into xpt::detail::sParams.
+ uint8_t mNumParams;
+
+ uint8_t mGetter : 1;
+ uint8_t mSetter : 1;
+ uint8_t mReflectable : 1;
+ uint8_t mOptArgc : 1;
+ uint8_t mContext : 1;
+ uint8_t mHasRetval : 1;
+ uint8_t mIsSymbol : 1;
+};
+
+// The fields in nsXPTMethodInfo were carefully ordered to minimize size.
+static_assert(sizeof(nsXPTMethodInfo) == 8, "wrong size");
+
+// This number is chosen to be no larger than the maximum number of parameters
+// any XPIDL-defined function needs; there is a static assert in the generated
+// code from xptcodegen.py to verify that decision. It is therefore also the
+// maximum number of stack allocated nsXPTCMiniVariant structures for argument
+// passing purposes in PrepareAndDispatch implementations.
+#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
+# define PARAM_BUFFER_COUNT 18
+#else
+# define PARAM_BUFFER_COUNT 14
+#endif
+
+/**
+ * A nsXPTConstantInfo is used to describe a single interface constant.
+ */
+struct nsXPTConstantInfo {
+ const char* Name() const { return xpt::detail::GetString(mName); }
+
+ JS::Value JSValue() const {
+ if (mSigned || mValue <= uint32_t(INT32_MAX)) {
+ return JS::Int32Value(int32_t(mValue));
+ }
+ return JS::DoubleValue(mValue);
+ }
+
+ ////////////////////////////////////////////////////////////////
+ // Ensure these fields are in the same order as xptcodegen.py //
+ ////////////////////////////////////////////////////////////////
+
+ uint32_t mName : 31; // Index into xpt::detail::mStrings.
+
+ // Whether the value should be interpreted as a int32_t or uint32_t.
+ uint32_t mSigned : 1;
+ uint32_t mValue; // The value stored as a u32
+};
+
+// The fields in nsXPTConstantInfo were carefully ordered to minimize size.
+static_assert(sizeof(nsXPTConstantInfo) == 8, "wrong size");
+
+/**
+ * Object representing the information required to wrap and unwrap DOMObjects.
+ *
+ * This object will not live in rodata as it contains relocations.
+ */
+struct nsXPTDOMObjectInfo {
+ nsresult Unwrap(JS::Handle<JS::Value> aHandle, void** aObj,
+ JSContext* aCx) const {
+ return mUnwrap(aHandle, aObj, aCx);
+ }
+
+ bool Wrap(JSContext* aCx, void* aObj,
+ JS::MutableHandle<JS::Value> aHandle) const {
+ return mWrap(aCx, aObj, aHandle);
+ }
+
+ void Cleanup(void* aObj) const { return mCleanup(aObj); }
+
+ ////////////////////////////////////////////////////////////////
+ // Ensure these fields are in the same order as xptcodegen.py //
+ ////////////////////////////////////////////////////////////////
+
+ nsresult (*mUnwrap)(JS::Handle<JS::Value> aHandle, void** aObj,
+ JSContext* aCx);
+ bool (*mWrap)(JSContext* aCx, void* aObj,
+ JS::MutableHandle<JS::Value> aHandle);
+ void (*mCleanup)(void* aObj);
+};
+
+namespace xpt {
+namespace detail {
+
+// The UntypedTArray type allows low-level access from XPConnect to nsTArray
+// internals without static knowledge of the array element type in question.
+class UntypedTArray : public nsTArray_base<nsTArrayFallibleAllocator,
+ nsTArray_RelocateUsingMemutils> {
+ public:
+ void* Elements() const { return static_cast<void*>(Hdr() + 1); }
+
+ // Changes the length and capacity to be at least large enough for aTo
+ // elements.
+ bool SetLength(const nsXPTType& aEltTy, uint32_t aTo) {
+ if (!EnsureCapacity<nsTArrayFallibleAllocator>(aTo, aEltTy.Stride())) {
+ return false;
+ }
+
+ if (mHdr != EmptyHdr()) {
+ mHdr->mLength = aTo;
+ }
+
+ return true;
+ }
+
+ // Free backing memory for the nsTArray object.
+ void Clear() {
+ if (mHdr != EmptyHdr() && !UsesAutoArrayBuffer()) {
+ nsTArrayFallibleAllocator::Free(mHdr);
+ }
+ mHdr = EmptyHdr();
+ }
+};
+
+//////////////////////////////////////////////
+// Raw typelib data stored in const statics //
+//////////////////////////////////////////////
+
+// XPIDL information
+extern const nsXPTInterfaceInfo sInterfaces[];
+extern const nsXPTType sTypes[];
+extern const nsXPTParamInfo sParams[];
+extern const nsXPTMethodInfo sMethods[];
+extern const nsXPTConstantInfo sConsts[];
+extern const nsXPTDOMObjectInfo sDOMObjects[];
+
+extern const char sStrings[];
+
+//////////////////////////////////////
+// Helper Methods for fetching data //
+//////////////////////////////////////
+
+inline const nsXPTInterfaceInfo* GetInterface(uint16_t aIndex) {
+ if (aIndex > 0 && aIndex <= sInterfacesSize) {
+ return &sInterfaces[aIndex - 1]; // 1-based as 0 is a marker.
+ }
+ return nullptr;
+}
+
+inline const nsXPTType& GetType(uint16_t aIndex) { return sTypes[aIndex]; }
+
+inline const nsXPTParamInfo& GetParam(uint16_t aIndex) {
+ return sParams[aIndex];
+}
+
+inline const nsXPTMethodInfo& GetMethod(uint16_t aIndex) {
+ return sMethods[aIndex];
+}
+
+inline const nsXPTConstantInfo& GetConstant(uint16_t aIndex) {
+ return sConsts[aIndex];
+}
+
+inline const nsXPTDOMObjectInfo& GetDOMObjectInfo(uint16_t aIndex) {
+ return sDOMObjects[aIndex];
+}
+
+inline const char* GetString(uint32_t aIndex) { return &sStrings[aIndex]; }
+
+} // namespace detail
+} // namespace xpt
+
+#define XPT_FOR_EACH_ARITHMETIC_TYPE(MACRO) \
+ MACRO(TD_INT8, int8_t) \
+ MACRO(TD_INT16, int16_t) \
+ MACRO(TD_INT32, int32_t) \
+ MACRO(TD_INT64, int64_t) \
+ MACRO(TD_UINT8, uint8_t) \
+ MACRO(TD_UINT16, uint16_t) \
+ MACRO(TD_UINT32, uint32_t) \
+ MACRO(TD_UINT64, uint64_t) \
+ MACRO(TD_FLOAT, float) \
+ MACRO(TD_DOUBLE, double) \
+ MACRO(TD_BOOL, bool) \
+ MACRO(TD_CHAR, char) \
+ MACRO(TD_WCHAR, char16_t)
+
+#define XPT_FOR_EACH_POINTER_TYPE(MACRO) \
+ MACRO(TD_VOID, void*) \
+ MACRO(TD_NSIDPTR, nsID*) \
+ MACRO(TD_PSTRING, char*) \
+ MACRO(TD_PWSTRING, wchar_t*) \
+ MACRO(TD_INTERFACE_TYPE, nsISupports*) \
+ MACRO(TD_INTERFACE_IS_TYPE, nsISupports*) \
+ MACRO(TD_LEGACY_ARRAY, void*) \
+ MACRO(TD_PSTRING_SIZE_IS, char*) \
+ MACRO(TD_PWSTRING_SIZE_IS, wchar_t*) \
+ MACRO(TD_DOMOBJECT, void*) \
+ MACRO(TD_PROMISE, mozilla::dom::Promise*)
+
+#define XPT_FOR_EACH_COMPLEX_TYPE(MACRO) \
+ MACRO(TD_UTF8STRING, nsCString) \
+ MACRO(TD_CSTRING, nsCString) \
+ MACRO(TD_ASTRING, nsString) \
+ MACRO(TD_NSID, nsID) \
+ MACRO(TD_JSVAL, JS::Value) \
+ MACRO(TD_ARRAY, xpt::detail::UntypedTArray)
+
+#define XPT_FOR_EACH_TYPE(MACRO) \
+ XPT_FOR_EACH_ARITHMETIC_TYPE(MACRO) \
+ XPT_FOR_EACH_POINTER_TYPE(MACRO) \
+ XPT_FOR_EACH_COMPLEX_TYPE(MACRO)
+
+inline size_t nsXPTType::Stride() const {
+ // Compute the stride to use when walking an array of the given type.
+ switch (Tag()) {
+#define XPT_TYPE_STRIDE(tag, type) \
+ case tag: \
+ return sizeof(type);
+ XPT_FOR_EACH_TYPE(XPT_TYPE_STRIDE)
+#undef XPT_TYPE_STRIDE
+ }
+
+ MOZ_CRASH("Unknown type");
+}
+
+#endif /* xptinfo_h */