summaryrefslogtreecommitdiff
path: root/xpcom/reflect
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/reflect')
-rw-r--r--xpcom/reflect/moz.build8
-rw-r--r--xpcom/reflect/xptcall/README6
-rw-r--r--xpcom/reflect/xptcall/genstubs.pl88
-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.cpp207
-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.build9
-rw-r--r--xpcom/reflect/xptcall/md/test/stub_test.cpp213
-rw-r--r--xpcom/reflect/xptcall/md/unix/Makefile.in79
-rw-r--r--xpcom/reflect/xptcall/md/unix/moz.build327
-rw-r--r--xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp66
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h17
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp140
-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.s67
-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_mips.S134
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S122
-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_netbsd.s95
-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_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_sparc_solaris_GCC3.s52
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s56
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s85
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s55
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp16
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp97
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp132
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp100
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp144
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_m68k.cpp130
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp195
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp190
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp99
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp142
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_netbsd_m68k.cpp143
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp149
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp97
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp74
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp63
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp128
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_netbsd.cpp115
-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_sparc64_openbsd.cpp69
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp131
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp128
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp131
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparcv9_solaris.cpp73
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp149
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp188
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_solaris.cpp67
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp219
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp189
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp238
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp113
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp205
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.s39
-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_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_netbsd.s70
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S72
-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_asm_sparcv9_solaris.s50
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_64_solaris_SUNW.s63
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_solaris_SUNW.s78
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp16
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp139
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp151
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp154
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp187
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_linux_m68k.cpp98
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp183
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp187
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp112
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp185
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_netbsd_m68k.cpp115
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp143
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp246
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp185
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp172
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp220
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_netbsd.cpp185
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp202
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp165
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp104
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp117
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp120
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp112
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparcv9_solaris.cpp101
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp190
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp204
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_solaris.cpp139
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_x86_solaris.cpp77
-rw-r--r--xpcom/reflect/xptcall/md/win32/moz.build45
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp45
-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.cpp59
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp106
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs.cpp227
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm335
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp197
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp297
-rw-r--r--xpcom/reflect/xptcall/moz.build23
-rw-r--r--xpcom/reflect/xptcall/porting.html216
-rw-r--r--xpcom/reflect/xptcall/status.html412
-rw-r--r--xpcom/reflect/xptcall/xptcall.cpp82
-rw-r--r--xpcom/reflect/xptcall/xptcall.h193
-rw-r--r--xpcom/reflect/xptcall/xptcprivate.h67
-rw-r--r--xpcom/reflect/xptcall/xptcstubsdecl.inc761
-rw-r--r--xpcom/reflect/xptcall/xptcstubsdef.inc252
-rw-r--r--xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp700
-rw-r--r--xpcom/reflect/xptinfo/ShimInterfaceInfo.h50
-rw-r--r--xpcom/reflect/xptinfo/TODO20
-rw-r--r--xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h119
-rw-r--r--xpcom/reflect/xptinfo/moz.build37
-rw-r--r--xpcom/reflect/xptinfo/nsIInterfaceInfo.idl101
-rw-r--r--xpcom/reflect/xptinfo/nsIInterfaceInfoManager.idl28
-rw-r--r--xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp742
-rw-r--r--xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp242
-rw-r--r--xpcom/reflect/xptinfo/xptiTypelibGuts.cpp74
-rw-r--r--xpcom/reflect/xptinfo/xptiWorkingSet.cpp53
-rw-r--r--xpcom/reflect/xptinfo/xptinfo.h236
-rw-r--r--xpcom/reflect/xptinfo/xptiprivate.h394
157 files changed, 20969 insertions, 0 deletions
diff --git a/xpcom/reflect/moz.build b/xpcom/reflect/moz.build
new file mode 100644
index 000000000..c04892d00
--- /dev/null
+++ b/xpcom/reflect/moz.build
@@ -0,0 +1,8 @@
+# -*- 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 000000000..0c401fe88
--- /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 000000000..16ae2006a
--- /dev/null
+++ b/xpcom/reflect/xptcall/genstubs.pl
@@ -0,0 +1,88 @@
+#!/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/xptiInterfaceInfoManager.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 000000000..a4b59aaf0
--- /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 000000000..04850b2e0
--- /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 000000000..f320e222c
--- /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 000000000..068db8b2f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/invoke_test.cpp
@@ -0,0 +1,207 @@
+/* -*- 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();
+ NS_IMETHOD callme1(int i, int j);
+ NS_IMETHOD callme2(int i, int j);
+ NS_IMETHOD callme3(int i, int j);
+};
+
+/*
+class baz : public base {
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1();
+ NS_IMETHOD callme2();
+ NS_IMETHOD callme3();
+ 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 000000000..10a9be51d
--- /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 000000000..f9af17aff
--- /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 000000000..2261c3ce6
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/moz.build
@@ -0,0 +1,9 @@
+# -*- 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 000000000..6c9559c65
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/stub_test.cpp
@@ -0,0 +1,213 @@
+/* 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();
+ NS_IMETHOD callme1(int i, int j);
+ NS_IMETHOD callme2(int i, int j);
+ NS_IMETHOD callme3(int i, int j);
+};
+
+class baz : public base {
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1();
+ NS_IMETHOD callme2();
+ NS_IMETHOD callme3();
+ 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/Makefile.in b/xpcom/reflect/xptcall/md/unix/Makefile.in
new file mode 100644
index 000000000..e4cdc389b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/Makefile.in
@@ -0,0 +1,79 @@
+#
+# 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/.
+
+######################################################################
+# HPPA
+######################################################################
+#
+# HP-UX/PA32
+#
+# for gas and gcc, check comment in xptcinvoke_asm_pa32.s
+ifeq ($(OS_ARCH),HP-UX)
+ifneq ($(CC),gcc)
+# #18875 Building the CPP's (CXX) optimized causes a crash
+CXXFLAGS := $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(CXXFLAGS))
+endif
+endif
+
+#
+# Linux/HPPA/gcc
+#
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(filter hppa hppa2.0 hppa1.1,$(OS_TEST)))
+ifndef GNU_CXX
+else
+# #434190 optimized builds crash
+CXXFLAGS := $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(CXXFLAGS))
+endif
+endif
+endif
+
+
+######################################################################
+# PowerPC
+######################################################################
+#
+# AIX/PPC
+#
+ifeq ($(OS_ARCH),AIX)
+# #24617 Building the CPP's (CXX) optimized causes a crash
+CXXFLAGS := $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(CXXFLAGS))
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(findstring mips, $(OS_TEST)))
+xptcstubs_asm_mips.o: $(DIST)/include/xptcstubsdef.inc
+endif
+endif
+
+ifeq ($(OS_ARCH),Darwin)
+xptcstubs_asm_ppc_darwin.s: xptcstubs_asm_ppc_darwin.s.m4 $(DIST)/include/xptcstubsdef.inc Makefile
+ gm4 $(INCLUDES) $< > $@
+endif
+
+ifeq ($(OS_ARCH),AIX)
+ifdef HAVE_64BIT_BUILD
+xptcstubs_asm_ppc_aix64.s: xptcstubs_asm_ppc_aix64.s.m4 $(DIST)/include/xptcstubsdef.inc Makefile
+ m4 -DAIX_OBJMODEL=$(AIX_OBJMODEL) $(INCLUDES) -I. $< > $@
+else
+xptcstubs_asm_ppc_aix.s: xptcstubs_asm_ppc_aix.s.m4 $(DIST)/include/xptcstubsdef.inc Makefile
+ m4 -DAIX_OBJMODEL=$(AIX_OBJMODEL) $(INCLUDES) -I. $< > $@
+endif
+endif
+
+ifeq ($(OS_ARCH),SunOS)
+ifeq (86,$(findstring 86,$(OS_TEST)))
+ifndef GNU_CC
+xptcstubsdef_asm.solx86: $(DIST)/include/xptcstubsdef.inc
+ sed \
+ -e 's/^\(STUB_ENTRY\)(\([0-9]\))/\11\(\2\)/' \
+ -e 's/^\(STUB_ENTRY\)(\([0-9][0-9]\))/\12\(\2\)/' \
+ -e 's/^\(STUB_ENTRY\)(\([0-9][0-9][0-9]\))/\13\(\2\)/' \
+ $(DIST)/include/xptcstubsdef.inc > $@
+endif
+endif
+endif
diff --git a/xpcom/reflect/xptcall/md/unix/moz.build b/xpcom/reflect/xptcall/md/unix/moz.build
new file mode 100644
index 000000000..1d182bbd6
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/moz.build
@@ -0,0 +1,327 @@
+# -*- 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['OS_TEST'] == 'powerpc':
+ SOURCES += [
+ '!xptcstubs_asm_ppc_darwin.s',
+ 'xptcinvoke_asm_ppc_rhapsody.s',
+ ]
+ if '86' in CONFIG['OS_TEST'] and CONFIG['OS_TEST'] != 'x86_64':
+ DEFINES['MOZ_NEED_LEADING_UNDERSCORE'] = True
+
+if CONFIG['OS_ARCH'] == 'GNU':
+ if CONFIG['CPU_ARCH'] == 'x86':
+ SOURCES += [
+ 'xptcinvoke_gcc_x86_unix.cpp',
+ 'xptcstubs_gcc_x86_unix.cpp'
+ ]
+
+if CONFIG['OS_ARCH'] in ('Linux', 'Bitrig', 'DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD') or \
+ CONFIG['OS_ARCH'].startswith('GNU_'):
+ if CONFIG['OS_TEST'] == 'x86_64':
+ SOURCES += [
+ 'xptcinvoke_x86_64_unix.cpp',
+ 'xptcstubs_x86_64_linux.cpp',
+ ]
+ elif '86' in CONFIG['OS_TEST']:
+ SOURCES += [
+ 'xptcinvoke_gcc_x86_unix.cpp',
+ 'xptcstubs_gcc_x86_unix.cpp'
+ ]
+
+if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'):
+ if 'ia64' in CONFIG['OS_TEST']:
+ SOURCES += [
+ 'xptcinvoke_asm_ipf64.s',
+ 'xptcinvoke_ipf64.cpp',
+ 'xptcstubs_asm_ipf64.s',
+ 'xptcstubs_ipf64.cpp'
+ ]
+
+if CONFIG['OS_ARCH'] == 'SunOS' and '86' in CONFIG['OS_TEST']:
+ GENERATED_FILES = [
+ 'xptcstubsdef_asm.solx86',
+ ]
+ if CONFIG['OS_TEST'] == 'x86_64':
+ if CONFIG['GNU_CC']:
+ SOURCES += [
+ 'xptcinvoke_x86_64_unix.cpp',
+ 'xptcstubs_x86_64_linux.cpp'
+ ]
+ else:
+ ASFLAGS += ['-xarch=amd64']
+ SOURCES += [
+ 'xptcinvoke_x86_64_solaris.cpp',
+ 'xptcstubs_asm_x86_64_solaris_SUNW.s',
+ 'xptcstubs_x86_64_solaris.cpp',
+ ]
+ else:
+ if CONFIG['GNU_CC']:
+ SOURCES += [
+ 'xptcinvoke_gcc_x86_unix.cpp',
+ 'xptcstubs_gcc_x86_unix.cpp'
+ ]
+ else:
+ SOURCES += [
+ 'xptcinvoke_asm_x86_solaris_SUNW.s',
+ 'xptcinvoke_x86_solaris.cpp',
+ 'xptcstubs_asm_x86_solaris_SUNW.s',
+ 'xptcstubs_x86_solaris.cpp'
+ ]
+
+if CONFIG['OS_TEST'] == '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['CPU_ARCH'] == 'arm' or CONFIG['OS_TEST'] == 'sa110':
+ 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['CPU_ARCH'] == '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['OS_TEST'] == '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['OS_TEST'] in ('hppa', 'hppa2.0', 'hppa1.1'):
+ if CONFIG['GNU_CXX']:
+ 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'] == 'NetBSD':
+ if CONFIG['OS_TEST'] in ('amiga', 'atari', 'hp300', 'mac68k', 'mvme68k',
+ 'next68k', 'sun3', 'sun3x', 'x68k'):
+ SOURCES += [
+ 'xptcinvoke_netbsd_m68k.cpp',
+ 'xptcstubs_netbsd_m68k.cpp'
+ ]
+
+if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD', 'NetBSD', 'OpenBSD'):
+ if CONFIG['OS_TEST'] == 'aarch64':
+ SOURCES += [
+ 'xptcinvoke_aarch64.cpp',
+ 'xptcinvoke_asm_aarch64.s',
+ 'xptcstubs_aarch64.cpp',
+ 'xptcstubs_asm_aarch64.s',
+ ]
+ if CONFIG['OS_TEST'] == 'm68k':
+ SOURCES += [
+ 'xptcinvoke_linux_m68k.cpp',
+ 'xptcstubs_linux_m68k.cpp',
+ ]
+ if 'mips' in CONFIG['OS_TEST']:
+ if 'mips64' in CONFIG['OS_TEST']:
+ SOURCES += [
+ 'xptcinvoke_asm_mips64.S',
+ 'xptcinvoke_mips64.cpp',
+ 'xptcstubs_asm_mips64.S',
+ 'xptcstubs_mips64.cpp',
+ ]
+ else:
+ SOURCES += [
+ 'xptcinvoke_asm_mips.S',
+ 'xptcinvoke_mips.cpp',
+ 'xptcstubs_asm_mips.S',
+ 'xptcstubs_mips.cpp',
+ ]
+
+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['OS_TEST'] == 'powerpc':
+ 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['OS_TEST'] in ('powerpc64', 'powerpc64le'):
+ 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['OS_TEST'] in ('macppc', 'bebox', 'ofppc', 'prep', 'amigappc'):
+ if CONFIG['OS_ARCH'] == 'NetBSD':
+ SOURCES += [
+ 'xptcinvoke_asm_ppc_netbsd.s',
+ 'xptcinvoke_ppc_netbsd.cpp',
+ 'xptcstubs_asm_ppc_netbsd.s',
+ 'xptcstubs_ppc_netbsd.cpp',
+ ]
+
+if CONFIG['OS_ARCH'] == 'OpenBSD' and CONFIG['OS_TEST'] == 'powerpc':
+ 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 'sparc' in CONFIG['OS_TEST']:
+ 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['OS_TEST'] == '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['OS_TEST'] == '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') and CONFIG['OS_TEST'] == 'sparc64':
+ SOURCES += [
+ 'xptcinvoke_asm_sparc64_openbsd.s',
+ 'xptcinvoke_sparc64_openbsd.cpp',
+ 'xptcstubs_asm_sparc64_openbsd.s',
+ 'xptcstubs_sparc64_openbsd.cpp',
+ ]
+
+if CONFIG['OS_ARCH'] == 'SunOS' and '86' not in CONFIG['OS_TEST']:
+ if CONFIG['HAVE_64BIT_BUILD']:
+ ASFLAGS += ['-xarch=v9']
+ SOURCES += [
+ 'xptcinvoke_sparcv9_solaris.cpp',
+ 'xptcstubs_sparcv9_solaris.cpp',
+ ]
+ else:
+ SOURCES += [
+ 'xptcinvoke_sparc_solaris.cpp',
+ 'xptcstubs_sparc_solaris.cpp',
+ ]
+ if CONFIG['GNU_CC']:
+ SOURCES += [
+ 'xptcinvoke_asm_sparc_solaris_GCC3.s',
+ 'xptcstubs_asm_sparc_solaris.s',
+ ]
+ else:
+ if CONFIG['HAVE_64BIT_BUILD']:
+ SOURCES += [
+ 'xptcinvoke_asm_sparcv9_solaris_SUNW.s',
+ 'xptcstubs_asm_sparcv9_solaris.s',
+ ]
+ else:
+ SOURCES += [
+ 'xptcinvoke_asm_sparc_solaris_SUNW.s',
+ 'xptcstubs_asm_sparc_solaris.s',
+ ]
+
+if CONFIG['OS_ARCH'] == 'Linux':
+ if CONFIG['OS_TEST'] == 's390':
+ SOURCES += [
+ 'xptcinvoke_linux_s390.cpp',
+ 'xptcstubs_linux_s390.cpp',
+ ]
+ CXXFLAGS += [
+ '-fno-strict-aliasing',
+ '-fno-inline',
+ '-fomit-frame-pointer',
+ '-mbackchain',
+ ]
+ elif CONFIG['OS_TEST'] == 's390x':
+ SOURCES += [
+ 'xptcinvoke_linux_s390x.cpp',
+ 'xptcstubs_linux_s390x.cpp',
+ ]
+ CXXFLAGS += [
+ '-fno-strict-aliasing',
+ '-fno-inline',
+ '-fomit-frame-pointer',
+ '-mbackchain',
+ ]
+
+FINAL_LIBRARY = 'xul'
+
+LOCAL_INCLUDES += [
+ '../..',
+ '/xpcom/reflect/xptinfo',
+]
+
+NO_PGO = True
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 000000000..0cb327a3d
--- /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 000000000..733646c49
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h
@@ -0,0 +1,17 @@
+/* -*- 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 000000000..e5807dbcd
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.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"
+
+#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
+
+/*
+ * 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->IsPtrData()) {
+ word = (uint64_t)s->ptr;
+ } 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 _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 000000000..dc111e435
--- /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 000000000..4cd5eb47d
--- /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->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ 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_BLACKLIST
+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->IsPtrData()) {
+ copy_word(ireg_args, stk, end, (uint32_t)s->ptr);
+ 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 000000000..1b0c214ea
--- /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 000000000..4ec7dd20f
--- /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 000000000..efe691a68
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.s
@@ -0,0 +1,67 @@
+/* -*- 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/. */
+
+ .section ".text"
+ .globl _NS_InvokeByIndex
+ .type _NS_InvokeByIndex,@function
+
+/*
+ * _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ * uint32_t paramCount, nsXPTCVariant* params)
+ */
+
+_NS_InvokeByIndex:
+ # set up frame
+ stp x29, x30, [sp,#-32]!
+ mov x29, sp
+ stp x19, x20, [sp,#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
+
+ add sp, sp, w19, uxth #3
+ ldp x19, x20, [sp,#16]
+ ldp x29, x30, [sp],#32
+ ret
+
+ .size _NS_InvokeByIndex, . - _NS_InvokeByIndex
+
+
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 000000000..794c4f5c1
--- /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 000000000..140c44117
--- /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 ; .previous
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 000000000..32ff3b356
--- /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 000000000..eef34de7f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S
@@ -0,0 +1,122 @@
+/* -*- 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 sp, 0(sp) # get orig sp back
+
+ REG_L a0, A0OFF(sp) # a0 - that
+ REG_L a1, A1OFF(sp) # 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)
+
+ # save away our stack pointer and create
+ # the stack pointer for the function
+ move s0, sp
+ move sp, t3
+
+ jalr t9
+
+ 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 000000000..6fa9a86ba
--- /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 000000000..7a207addf
--- /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 000000000..37211c885
--- /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
+ ld 29,-24(r1) # Restore NVGPRS
+ ld 30,-16(r1)
+ ld 31,-8(r1)
+ mtlr 0
+ 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 ; .previous
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 000000000..eb6b6661d
--- /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 000000000..722583de5
--- /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 000000000..414a6536f
--- /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 000000000..e87382286
--- /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 ; .previous
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_netbsd.s
new file mode 100644
index 000000000..33650f399
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_netbsd.s
@@ -0,0 +1,95 @@
+# -*- 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 XPTC_InvokeByIndex
+ .type XPTC_InvokeByIndex,@function
+
+#
+# XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+XPTC_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 sapce 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,3 # convert to offset ( *= 8 )
+ addi r4,r4,8 # skip first two vtable entries
+ add r4,r4,r5
+ lhz r0,0(r4) # virtual base offset
+ extsh r0,r0
+ add r3,r3,r0
+ lwz r0,4(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
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 000000000..f02c0b220
--- /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 ; .previous
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 000000000..1dc12b2b3
--- /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_sparc64_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s
new file mode 100644
index 000000000..dfd6189f8
--- /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 000000000..36196805e
--- /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 000000000..893432a5e
--- /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 000000000..1ef695370
--- /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_sparc_solaris_GCC3.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s
new file mode 100644
index 000000000..54adcd147
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s
@@ -0,0 +1,52 @@
+/* -*- 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
+ * solaris/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 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+ 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_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s
new file mode 100644
index 000000000..013770392
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s
@@ -0,0 +1,56 @@
+/* -*- 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 NS_InvokeByIndex
+ .type NS_InvokeByIndex, #function
+/*
+ NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+*/
+NS_InvokeByIndex:
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+ sll %i2,3,%l0 ! assume the worst case
+ ! paramCount * 2 * 4 bytes
+ cmp %l0, 0 ! are there any args? If not,
+ be .invoke ! no need to copy args to stack
+
+ sub %sp,%l0,%sp ! create the additional stack space
+ add %sp,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
+
+!
+! load arguments from stack into the outgoing registers
+!
+ ld [%sp + 72],%o1
+ ld [%sp + 76],%o2
+ ld [%sp + 80],%o3
+ ld [%sp + 84],%o4
+ ld [%sp + 88],%o5
+
+!
+! calculate the target address from the vtable
+!
+.invoke:
+ sll %i1,2,%l0 ! index *= 4
+ add %l0,8,%l0 ! there are 2 extra entries in the vTable
+ ld [%i0],%l1 ! *that --> address of vtable
+ ld [%l0 + %l1],%l0 ! that->vtable[index * 4 + 8] --> 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_sparcv9_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s
new file mode 100644
index 000000000..34861abc0
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s
@@ -0,0 +1,85 @@
+/* -*- 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
+
+ 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 %d2
+ ldd [%sp + 0x7ff + 136],%d2
+ ldd [%sp + 0x7ff + 144],%d4
+ ldd [%sp + 0x7ff + 152],%d6
+ ldd [%sp + 0x7ff + 160],%d8
+ ldd [%sp + 0x7ff + 168],%d10
+ ldd [%sp + 0x7ff + 176],%d12
+ ldd [%sp + 0x7ff + 184],%d14
+ ldd [%sp + 0x7ff + 192],%d16
+ ldd [%sp + 0x7ff + 200],%d18
+ ldd [%sp + 0x7ff + 208],%d20
+ ldd [%sp + 0x7ff + 216],%d22
+ ldd [%sp + 0x7ff + 224],%d24
+ ldd [%sp + 0x7ff + 232],%d26
+ ldd [%sp + 0x7ff + 240],%d28
+ ldd [%sp + 0x7ff + 248],%d30
+
+!
+! 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_x86_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s
new file mode 100644
index 000000000..af665a162
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s
@@ -0,0 +1,55 @@
+ .globl NS_InvokeByIndex
+ .type NS_InvokeByIndex, @function
+NS_InvokeByIndex:
+ push %ebp
+ movl %esp,%ebp
+ push %ebx
+ call .CG0.66
+.CG0.66:
+ pop %ebx
+ addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx
+ push 20(%ebp)
+ push 16(%ebp)
+ push 12(%ebp)
+ push 8(%ebp)
+ / INLINE: invoke_by_index
+
+
+
+ pushl %ebx
+ pushl %esi
+ movl %esp, %ebx
+
+ pushl 0x14(%ebp)
+ pushl 0x10(%ebp)
+ call invoke_count_words
+ mov %ebx, %esp
+
+ sall $0x2 , %eax
+ subl %eax, %esp
+ movl %esp, %esi
+
+ pushl %esp
+ pushl 0x14(%ebp)
+ pushl 0x10(%ebp)
+ call invoke_copy_to_stack
+ movl %esi, %esp
+
+ movl 0x8(%ebp), %ecx
+ pushl %ecx
+ movl (%ecx), %edx
+ movl 0xc(%ebp), %eax
+ movl 0x8(%edx, %eax, 4), %edx
+
+ call *%edx
+ mov %ebx, %esp
+ popl %esi
+ popl %ebx
+ / INLINE_END
+ addl $16,%esp
+ pop %ebx
+ movl %ebp,%esp
+ pop %ebp
+ ret
+ .size NS_InvokeByIndex, . - NS_InvokeByIndex
+
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 000000000..04407db39
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp
@@ -0,0 +1,16 @@
+/* -*- 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"
+#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 000000000..d4a8a12fb
--- /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->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ 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 000000000..1500f3175
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.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/. */
+
+#include "xptcprivate.h"
+
+#include <iostream.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 000000000..c2a4dd088
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp
@@ -0,0 +1,100 @@
+
+/* -*- 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 000000000..dc111e435
--- /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_m68k.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_m68k.cpp
new file mode 100644
index 000000000..6f2934cbc
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_m68k.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"
+
+// Remember that these 'words' are 32bit DWORDS
+
+extern "C" {
+ 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;
+ }
+
+ 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)
+ {
+ // 8 and 16 bit types should be promoted to 32 bits when copying
+ // onto the stack.
+ case nsXPTType::T_I8 : *((uint32_t*)d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((uint32_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; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((uint32_t*)d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*)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;
+ }
+ }
+ }
+}
+
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ uint32_t result, n;
+
+ n = invoke_count_words(paramCount, params) * 4;
+
+ __asm__ __volatile__(
+ "subl %5, %%sp\n\t" /* make room for params */
+ "movel %4, %%sp@-\n\t"
+ "movel %3, %%sp@-\n\t"
+ "pea %%sp@(8)\n\t"
+ "jbsr invoke_copy_to_stack\n\t" /* copy params */
+ "addw #12, %%sp\n\t"
+ "movel %1, %%sp@-\n\t"
+ "movel %1@, %%a0\n\t"
+ "movel %%a0@(%2:l:4), %%a0\n\t"
+ "jbsr %%a0@\n\t" /* safe to not cleanup sp */
+ "lea %%sp@(4,%5:l), %%sp\n\t"
+ "movel %%d0, %0"
+ : "=d" (result) /* %0 */
+ : "a" (that), /* %1 */
+ "d" (methodIndex), /* %2 */
+ "g" (paramCount), /* %3 */
+ "g" (params), /* %4 */
+ "d" (n) /* %5 */
+ : "a0", "a1", "d0", "d1", "memory"
+ );
+
+ return result;
+}
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 000000000..573dfb00c
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp
@@ -0,0 +1,195 @@
+/* -*- 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_BLACKLIST
+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 000000000..86478a850
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp
@@ -0,0 +1,190 @@
+/* -*- 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 :
+ 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->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)
+ *((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_BLACKLIST
+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_mips.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp
new file mode 100644
index 000000000..f6585e7f0
--- /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->IsPtrData())
+ 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->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ 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 000000000..1dd54f96f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.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/. */
+
+/* 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->IsPtrData()) {
+ if (i < N_ARG_REGS)
+ regs[i] = (uint64_t)s->ptr;
+ else
+ *d++ = (uint64_t)s->ptr;
+ 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:
+ 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_netbsd_m68k.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_netbsd_m68k.cpp
new file mode 100644
index 000000000..47e0e7666
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_netbsd_m68k.cpp
@@ -0,0 +1,143 @@
+/* -*- 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
+
+#if !defined(__NetBSD__) || !defined(__m68k__)
+#error This code is for NetBSD/m68k only
+#endif
+
+extern "C" {
+ 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)
+ {
+ // 8 and 16 bit types should be promoted to 32 bits when copying
+ // onto the stack.
+ case nsXPTType::T_I8 : *((uint32_t*)d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((uint32_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; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((uint32_t*)d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*)d) = s->val.c; break;
+ // wchar_t is an int (32 bits) on NetBSD
+ 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;
+ }
+ }
+ }
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ uint32_t result;
+
+ __asm__ __volatile__(
+ "movl %4, sp@-\n\t"
+ "movl %3, sp@-\n\t"
+ "jbsr _invoke_count_words\n\t" /* count words */
+ "addql #8, sp\n\t"
+ "lsll #2, d0\n\t" /* *= 4 */
+ "movl sp, a2\n\t" /* save original sp */
+ "subl d0, sp\n\t" /* make room for params */
+ "movl sp, a0\n\t"
+ "movl %4, sp@-\n\t"
+ "movl %3, sp@-\n\t"
+ "movl a0, sp@-\n\t"
+ "jbsr _invoke_copy_to_stack\n\t" /* copy params */
+ "addl #12, sp\n\t"
+ "movl %1, a0\n\t"
+ "movl a0@, a1\n\t"
+ "movl %2, d0\n\t" /* function index */
+ "movl a0, d1\n\t"
+ "movw a1@(8,d0:l:8), a0\n\t"
+ "addl a0, d1\n\t"
+ "movl a1@(12,d0:l:8), a1\n\t"
+ "movl d1, sp@-\n\t"
+ "jbsr a1@\n\t"
+ "movl a2, sp\n\t" /* restore original sp */
+ "movl d0, %0\n\t"
+ : "=g" (result) /* %0 */
+ : "g" (that), /* %1 */
+ "g" (methodIndex), /* %2 */
+ "g" (paramCount), /* %3 */
+ "g" (params) /* %4 */
+ : "a0", "a1", "a2", "d0", "d1", "memory"
+ );
+
+ return result;
+}
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 000000000..0e6d28fbd
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp
@@ -0,0 +1,149 @@
+
+/* -*- 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 000000000..c93dc4621
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.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
+
+// 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.
+
+// The PowerPC64 platform ABI can be found here:
+// http://www.freestandards.org/spec/ELF/ppc64/
+// and in particular:
+// http://www.freestandards.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-CALL
+
+#include <stdio.h>
+#include "xptcprivate.h"
+
+// 8 integral parameters are passed in registers, not including 'that'
+#define GPR_COUNT 7
+
+// 8 floating point parameters are passed in registers, floats are
+// promoted to doubles when passed in registers
+#define FPR_COUNT 13
+
+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(uint64_t* gpregs,
+ double* fpregs,
+ uint32_t paramCount,
+ nsXPTCVariant* s,
+ uint64_t* d)
+{
+ uint64_t tempu64;
+
+ for(uint32_t i = 0; i < paramCount; i++, s++) {
+ if(s->IsPtrData())
+ tempu64 = (uint64_t) s->ptr;
+ else {
+ switch(s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: tempu64 = s->val.i8; break;
+ case nsXPTType::T_I16: tempu64 = s->val.i16; break;
+ case nsXPTType::T_I32: tempu64 = s->val.i32; break;
+ case nsXPTType::T_I64: tempu64 = s->val.i64; break;
+ case nsXPTType::T_U8: tempu64 = s->val.u8; break;
+ case nsXPTType::T_U16: tempu64 = s->val.u16; break;
+ case nsXPTType::T_U32: tempu64 = s->val.u32; break;
+ case nsXPTType::T_U64: tempu64 = s->val.u64; break;
+ case nsXPTType::T_BOOL: tempu64 = s->val.b; break;
+ case nsXPTType::T_CHAR: tempu64 = s->val.c; break;
+ case nsXPTType::T_WCHAR: tempu64 = s->val.wc; break;
+ default: tempu64 = (uint64_t) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (i < FPR_COUNT)
+ fpregs[i] = s->val.d;
+ else
+ *(double *)d = s->val.d;
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (i < FPR_COUNT) {
+ fpregs[i] = s->val.f; // if passed in registers, floats are promoted to doubles
+ } else {
+ float *p = (float *)d;
+#ifndef __LITTLE_ENDIAN__
+ p++;
+#endif
+ *p = s->val.f;
+ }
+ }
+ else {
+ if (i < GPR_COUNT)
+ gpregs[i] = tempu64;
+ else
+ *d = tempu64;
+ }
+ if (i >= 7)
+ d++;
+ }
+}
+
+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 000000000..ba2a5dab0
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp
@@ -0,0 +1,74 @@
+/* -*- 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 000000000..616c2f687
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp
@@ -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/. */
+
+/* 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 000000000..deb72db8f
--- /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_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_netbsd.cpp
new file mode 100644
index 000000000..515e8c50b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_netbsd.cpp
@@ -0,0 +1,115 @@
+/* -*- 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 XPTC_InvokeByIndex() is to map a platform
+// indepenpent call to the platform ABI. To do that,
+// XPTC_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. 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;
+ if (gpr < GPR_COUNT)
+ gpr += 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;
+ d += 1;
+ if (gpr < GPR_COUNT)
+ gpr += 1;
+ }
+ }
+ 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"
+XPTC_PUBLIC_API(nsresult)
+XPTC_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 000000000..5353220fe
--- /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 000000000..1a40cfeea
--- /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_sparc64_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp
new file mode 100644
index 000000000..050f9414d
--- /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->IsPtrData())
+ {
+ *l_d = (uint64_t)l_s->ptr;
+ 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 000000000..126ef1dad
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp
@@ -0,0 +1,131 @@
+/* -*- 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 000000000..9b2e4f858
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.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 */
+
+#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 000000000..126ef1dad
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp
@@ -0,0 +1,131 @@
+/* -*- 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_sparcv9_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparcv9_solaris.cpp
new file mode 100644
index 000000000..0d2d6b0a8
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparcv9_solaris.cpp
@@ -0,0 +1,73 @@
+/* -*- 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
+
+/* Prototype specifies unmangled function name */
+extern "C" uint64_t
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s);
+
+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->IsPtrData())
+ {
+ *l_d = (uint64_t)l_s->ptr;
+ 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 : *((uint64_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_x86_64_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp
new file mode 100644
index 000000000..0d3424366
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp
@@ -0,0 +1,149 @@
+/* -*- 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 "alloca.h"
+
+// 6 integral parameters are passed in registers
+const uint32_t GPR_COUNT = 6;
+
+// 8 floating point parameters are passed in SSE registers
+const uint32_t FPR_COUNT = 8;
+
+// Remember that these 'words' are 64-bit long
+static inline void
+invoke_count_words(uint32_t paramCount, nsXPTCVariant * s,
+ uint32_t & nr_gpr, uint32_t & nr_fpr, uint32_t & nr_stack)
+{
+ nr_gpr = 1; // skip one GP register for 'that'
+ nr_fpr = 0;
+ nr_stack = 0;
+
+ /* Compute number of eightbytes of class MEMORY. */
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (!s->IsPtrData()
+ && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) {
+ if (nr_fpr < FPR_COUNT)
+ nr_fpr++;
+ else
+ nr_stack++;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ nr_gpr++;
+ else
+ nr_stack++;
+ }
+ }
+}
+
+static void
+invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s,
+ uint64_t * gpregs, double * fpregs)
+{
+ uint32_t nr_gpr = 1; // skip one GP register for 'that'
+ uint32_t nr_fpr = 0;
+ uint64_t value;
+
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (s->IsPtrData())
+ value = (uint64_t) s->ptr;
+ 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->IsPtrData() && 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->IsPtrData() && 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;
+ }
+ }
+}
+
+// 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_BLACKLIST
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant * params)
+{
+ uint32_t nr_gpr, nr_fpr, nr_stack;
+ invoke_count_words(paramCount, params, nr_gpr, nr_fpr, nr_stack);
+
+ // Stack, if used, must be 16-bytes aligned
+ if (nr_stack)
+ nr_stack = (nr_stack + 1) & ~1;
+
+ // Load parameters to stack, if necessary
+ uint64_t *stack = (uint64_t *) __builtin_alloca(nr_stack * 8);
+ uint64_t gpregs[GPR_COUNT];
+ double fpregs[FPR_COUNT];
+ invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs);
+
+ switch (nr_fpr) {
+ case 8: asm("movupd %0, %xmm7" : : "xmm7" (fpregs[7]));
+ case 7: asm("movupd %0, %xmm6" : : "xmm6" (fpregs[6]));
+ case 6: asm("movupd %0, %xmm5" : : "xmm5" (fpregs[5]));
+ case 5: asm("movupd %0, %xmm4" : : "xmm4" (fpregs[4]));
+ case 4: asm("movupd %0, %xmm3" : : "xmm3" (fpregs[3]));
+ case 3: asm("movupd %0, %xmm2" : : "xmm2" (fpregs[2]));
+ case 2: asm("movupd %0, %xmm1" : : "xmm1" (fpregs[1]));
+ case 1: asm("movupd %0, %xmm0" : : "xmm0" (fpregs[0]));
+ case 0:;
+ }
+
+ // Ensure that assignments to SSE registers won't be optimized away
+ asm("" ::: "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7");
+
+ // Get pointer to method
+ uint64_t methodAddress = *((uint64_t *)that);
+ methodAddress += 16 + 8 * methodIndex;
+ methodAddress = *((uint64_t *)methodAddress);
+
+ typedef uint32_t (*Method)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
+ uint32_t result = ((Method)methodAddress)((uint64_t)that, gpregs[1], gpregs[2], gpregs[3], gpregs[4], gpregs[5]);
+ return result;
+}
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 000000000..08e519889
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.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/. */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+#include "xptcprivate.h"
+
+// 6 integral parameters are passed in registers
+const uint32_t GPR_COUNT = 6;
+
+// 8 floating point parameters are passed in SSE registers
+const uint32_t FPR_COUNT = 8;
+
+// Remember that these 'words' are 64-bit long
+static inline void
+invoke_count_words(uint32_t paramCount, nsXPTCVariant * s,
+ uint32_t & nr_stack)
+{
+ uint32_t nr_gpr;
+ uint32_t nr_fpr;
+ nr_gpr = 1; // skip one GP register for 'that'
+ nr_fpr = 0;
+ nr_stack = 0;
+
+ /* Compute number of eightbytes of class MEMORY. */
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (!s->IsPtrData()
+ && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) {
+ if (nr_fpr < FPR_COUNT)
+ nr_fpr++;
+ else
+ nr_stack++;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ nr_gpr++;
+ else
+ nr_stack++;
+ }
+ }
+}
+
+static void
+invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s,
+ uint64_t * gpregs, double * fpregs)
+{
+ uint32_t nr_gpr = 1u; // skip one GP register for 'that'
+ uint32_t nr_fpr = 0u;
+ uint64_t value = 0u;
+
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (s->IsPtrData())
+ value = (uint64_t) s->ptr;
+ 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->IsPtrData() && 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->IsPtrData() && 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;
+ }
+ }
+}
+
+// Disable avx for the next function to allow compilation with
+// -march=native on new machines, or similar hardcoded -march options.
+// Having avx enabled appears to change the alignment behavior of alloca
+// (apparently adding an extra 16 bytes) of padding/alignment (and using
+// 32-byte alignment instead of 16-byte). This seems to be the best
+// available workaround, given that this code, which should perhaps
+// better be written in assembly, is written in C++.
+#ifndef __clang__
+#pragma GCC push_options
+#pragma GCC target ("no-avx")
+#endif
+
+// 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_BLACKLIST
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant * params)
+{
+ uint32_t nr_stack;
+ invoke_count_words(paramCount, params, nr_stack);
+
+ // Stack, if used, must be 16-bytes aligned
+ if (nr_stack)
+ nr_stack = (nr_stack + 1) & ~1;
+
+ // Load parameters to stack, if necessary
+ uint64_t *stack = (uint64_t *) __builtin_alloca(nr_stack * 8);
+ uint64_t gpregs[GPR_COUNT];
+ double fpregs[FPR_COUNT];
+ invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs);
+
+ // We used to have switches to make sure we would only load the registers
+ // that are needed for this call. That produced larger code that was
+ // not faster in practice. It also caused compiler warnings about the
+ // variables being used uninitialized.
+ // We now just load every every register. There could still be a warning
+ // from a memory analysis tools that we are loading uninitialized stack
+ // positions.
+
+ // FIXME: this function depends on the above __builtin_alloca placing
+ // the array in the correct spot for the ABI.
+
+ // Load FPR registers from fpregs[]
+ double d0, d1, d2, d3, d4, d5, d6, d7;
+
+ d7 = fpregs[7];
+ d6 = fpregs[6];
+ d5 = fpregs[5];
+ d4 = fpregs[4];
+ d3 = fpregs[3];
+ d2 = fpregs[2];
+ d1 = fpregs[1];
+ d0 = fpregs[0];
+
+ // Load GPR registers from gpregs[]
+ uint64_t a0, a1, a2, a3, a4, a5;
+
+ a5 = gpregs[5];
+ a4 = gpregs[4];
+ a3 = gpregs[3];
+ a2 = gpregs[2];
+ a1 = gpregs[1];
+ a0 = (uint64_t) that;
+
+ // Get pointer to method
+ uint64_t methodAddress = *((uint64_t *)that);
+ methodAddress += 8 * methodIndex;
+ methodAddress = *((uint64_t *)methodAddress);
+
+ typedef nsresult (*Method)(uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t, uint64_t, double, double, double,
+ double, double, double, double, double);
+ nsresult result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5,
+ d0, d1, d2, d3, d4, d5,
+ d6, d7);
+ return result;
+}
+
+#ifndef __clang__
+#pragma GCC pop_options
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_solaris.cpp
new file mode 100644
index 000000000..f545fcc99
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_solaris.cpp
@@ -0,0 +1,67 @@
+/* -*- 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" {
+
+// Remember that these 'words' are 32bit DWORDS
+
+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;
+ }
+ result++;
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE :
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+void
+invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d)
+{
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+/* XXX: the following line is here (rather than as the default clause in
+ * the following switch statement) so that the Sun native compiler
+ * will generate the correct assembly code on the Solaris Intel
+ * platform. See the comments in bug #28817 for more details.
+ */
+
+ *((void**)d) = s->val.p;
+
+ 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;
+ }
+ }
+}
+
+}
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 000000000..571fb42a2
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp
@@ -0,0 +1,219 @@
+/* -*- 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 "xptiprivate.h"
+
+#ifndef __AARCH64EL__
+#error "Only little endian compatibility was tested"
+#endif
+
+/*
+ * 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_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 8
+#define PARAM_FPR_COUNT 8
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ const nsXPTMethodInfo* info;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ uint32_t paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if (paramCount > PARAM_BUFFER_COUNT) {
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ } else {
+ dispatchParams = paramBuffer;
+ }
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ 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 = &dispatchParams[i];
+
+ 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)gprData[next_gpr++];
+ } else {
+ dp->val.b = (bool)*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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if (dispatchParams != paramBuffer) {
+ delete [] dispatchParams;
+ }
+
+ return result;
+}
+
+// Load w17 with the constant 'n' and branch to SharedStub().
+# 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\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" \
+ "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 000000000..d538767e1
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.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 PARAM_BUFFER_COUNT = 16;
+ const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // 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 = &dispatchParams[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; 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..ef4f8514d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm.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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.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
+
+/* 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")
+ATTRIBUTE_USED;
+
+#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
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[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 : 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..27c2b3d02
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp
@@ -0,0 +1,113 @@
+/* -*- 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)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ nsIInterfaceInfo* iface_info = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[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;
+ }
+ }
+
+ result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..f63d0c1e2
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp
@@ -0,0 +1,205 @@
+/* -*- 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 "xptiprivate.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)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..6603a4f25
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.s
@@ -0,0 +1,39 @@
+# 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
+
+ .section ".text"
+ .globl SharedStub
+ .hidden SharedStub
+ .type SharedStub,@function
+SharedStub:
+ stp x29, x30, [sp,#-16]!
+ mov x29, sp
+
+ 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 PrepareAndDispatch
+
+ add sp, sp, #8*(NGPREGS+NFPREGS)
+ ldp x29, x30, [sp],#16
+ ret
+
+ .size SharedStub, . - SharedStub
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 000000000..720dd6cc7
--- /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 000000000..4c07836d7
--- /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 ; .previous
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 000000000..d17301634
--- /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 000000000..33c7b1492
--- /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 000000000..11d851536
--- /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 000000000..9e86848fc
--- /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 000000000..b45d7763b
--- /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 000000000..877e262b9
--- /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 ; .previous
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 000000000..6dabf334d
--- /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 000000000..24d713cc9
--- /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 000000000..dda537850
--- /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 000000000..72a5a9f4b
--- /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 ; .previous
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_netbsd.s
new file mode 100644
index 000000000..8d43165ba
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_netbsd.s
@@ -0,0 +1,70 @@
+# -*- 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
+
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 000000000..dcca08205
--- /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 ; .previous
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 000000000..ab97a890c
--- /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 000000000..9b448d7c7
--- /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 000000000..871556d4c
--- /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 000000000..9b448d7c7
--- /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_asm_sparcv9_solaris.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparcv9_solaris.s
new file mode 100644
index 000000000..ab97a890c
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparcv9_solaris.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_x86_64_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_64_solaris_SUNW.s
new file mode 100644
index 000000000..aa6d84434
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_64_solaris_SUNW.s
@@ -0,0 +1,63 @@
+#define STUB_ENTRY1(nn) \
+ .globl __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_; \
+ .hidden __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_; \
+ .type __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_, @function; \
+__1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_: \
+ movl $/**/nn/**/, %eax; \
+ jmp SharedStub; \
+ .size __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_ \
+
+#define STUB_ENTRY2(nn) \
+ .globl __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_; \
+ .hidden __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_; \
+ .type __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_, @function; \
+__1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_: \
+ movl $/**/nn/**/, %eax; \
+ jmp SharedStub; \
+ .size __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_ \
+
+#define STUB_ENTRY3(nn) \
+ .globl __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_; \
+ .hidden __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_; \
+ .type __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_, @function; \
+__1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_: \
+ movl $/**/nn/**/, %eax; \
+ jmp SharedStub; \
+ .size __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_ \
+
+// static nsresult SharedStub(uint32_t methodIndex)
+ .type SharedStub, @function;
+ SharedStub:
+ // make room for gpregs (48), fpregs (64)
+ pushq %rbp;
+ movq %rsp,%rbp;
+ subq $112,%rsp;
+ // save GP registers
+ movq %rdi,-112(%rbp);
+ movq %rsi,-104(%rbp);
+ movq %rdx, -96(%rbp);
+ movq %rcx, -88(%rbp);
+ movq %r8 , -80(%rbp);
+ movq %r9 , -72(%rbp);
+ leaq -112(%rbp),%rcx;
+ // save FP registers
+ movsd %xmm0,-64(%rbp);
+ movsd %xmm1,-56(%rbp);
+ movsd %xmm2,-48(%rbp);
+ movsd %xmm3,-40(%rbp);
+ movsd %xmm4,-32(%rbp);
+ movsd %xmm5,-24(%rbp);
+ movsd %xmm6,-16(%rbp);
+ movsd %xmm7, -8(%rbp);
+ leaq -64(%rbp),%r8;
+ // rdi has the 'self' pointer already
+ movl %eax,%esi;
+ leaq 16(%rbp),%rdx;
+ call PrepareAndDispatch@plt;
+ leave;
+ ret;
+ .size SharedStub, . - SharedStub
+
+#define SENTINEL_ENTRY(nn)
+
+#include "xptcstubsdef_asm.solx86"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_solaris_SUNW.s
new file mode 100644
index 000000000..76bdcf925
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_solaris_SUNW.s
@@ -0,0 +1,78 @@
+#define STUB_ENTRY1(nn) \
+ .globl __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_; \
+ .type __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_, @function; \
+__1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_: \
+ push %ebp; \
+ movl %esp,%ebp; \
+ andl $-16,%esp; \
+ push %ebx; \
+ call .CG4./**/nn/**/; \
+.CG4./**/nn/**/: \
+ pop %ebx; \
+ addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx; \
+ leal 0xc(%ebp), %ecx; \
+ pushl %ecx; \
+ pushl $/**/nn/**/; \
+ movl 0x8(%ebp), %ecx; \
+ pushl %ecx; \
+ call __1cSPrepareAndDispatch6FpnOnsXPTCStubBase_IpI_I_; \
+ addl $0xc , %esp; \
+ pop %ebx; \
+ movl %ebp,%esp; \
+ pop %ebp; \
+ ret ; \
+ .size __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_ \
+
+#define STUB_ENTRY2(nn) \
+ .globl __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_; \
+ .type __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_, @function; \
+__1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_: \
+ push %ebp; \
+ movl %esp,%ebp; \
+ andl $-16,%esp; \
+ push %ebx; \
+ call .CG4./**/nn/**/; \
+.CG4./**/nn/**/: \
+ pop %ebx; \
+ addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx; \
+ leal 0xc(%ebp), %ecx; \
+ pushl %ecx; \
+ pushl $/**/nn/**/; \
+ movl 0x8(%ebp), %ecx; \
+ pushl %ecx; \
+ call __1cSPrepareAndDispatch6FpnOnsXPTCStubBase_IpI_I_; \
+ addl $0xc , %esp; \
+ pop %ebx; \
+ movl %ebp,%esp; \
+ pop %ebp; \
+ ret ; \
+ .size __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_ \
+
+#define STUB_ENTRY3(nn) \
+ .globl __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_; \
+ .type __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_, @function; \
+__1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_: \
+ push %ebp; \
+ movl %esp,%ebp; \
+ andl $-16,%esp; \
+ push %ebx; \
+ call .CG4./**/nn/**/; \
+.CG4./**/nn/**/: \
+ pop %ebx; \
+ addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx; \
+ leal 0xc(%ebp), %ecx; \
+ pushl %ecx; \
+ pushl $/**/nn/**/; \
+ movl 0x8(%ebp), %ecx; \
+ pushl %ecx; \
+ call __1cSPrepareAndDispatch6FpnOnsXPTCStubBase_IpI_I_; \
+ addl $0xc , %esp; \
+ pop %ebx; \
+ movl %ebp,%esp; \
+ pop %ebp; \
+ ret ; \
+ .size __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_ \
+
+#define SENTINEL_ENTRY(nn)
+
+#include "xptcstubsdef_asm.solx86"
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 000000000..49edfca44
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp
@@ -0,0 +1,16 @@
+/* -*- 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"
+#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 000000000..6811a26ad
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.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)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..e2d37e4f5
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp
@@ -0,0 +1,151 @@
+
+/* -*- 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 "xptiprivate.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)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ nsresult result = NS_ERROR_FAILURE;
+ 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();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for(i = 0; i < paramCount; ++i)
+ {
+ int isfloat = 0;
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..fea9e8e3d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp
@@ -0,0 +1,154 @@
+
+/* -*- 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 "xptiprivate.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)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ nsresult result = NS_ERROR_FAILURE;
+ 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();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for(i = 0; i < paramCount; ++i)
+ {
+ int isfloat = 0;
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..d9c41aee7
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp
@@ -0,0 +1,187 @@
+/* -*- 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 "xptiprivate.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 PARAM_BUFFER_COUNT = 16;
+ const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ // 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 = &dispatchParams[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; 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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_m68k.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_m68k.cpp
new file mode 100644
index 000000000..3720a5c37
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_m68k.cpp
@@ -0,0 +1,98 @@
+/* -*- 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 "xptiprivate.h"
+
+extern "C" {
+ nsresult ATTRIBUTE_USED
+ PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+ {
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+
+ switch(type)
+ {
+ // the 8 and 16 bit types will have been promoted to 32 bits before
+ // being pushed onto the stack. Since the 68k is big endian, we
+ // need to skip over the leading high order bytes.
+ case nsXPTType::T_I8 : dp->val.i8 = *(((int8_t*) ap) + 3); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(((int16_t*) ap) + 1); 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) + 3); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(((uint16_t*)ap) + 1); 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 = *((uint32_t* ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(((char*) ap) + 3); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+ }
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ void *frame = __builtin_frame_address(0); \
+ return PrepareAndDispatch(this, n, (uint32_t*)frame + 3); \
+}
+
+#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 000000000..cf4ab1268
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.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. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+static nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint32_t* a_gpr, uint64_t *a_fpr, uint32_t *a_ov)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ 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 = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..189cceb82
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp
@@ -0,0 +1,187 @@
+/* -*- 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 "xptiprivate.h"
+
+static nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint64_t* a_gpr, uint64_t *a_fpr, uint64_t *a_ov)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ 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 = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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_mips.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp
new file mode 100644
index 000000000..75f8562ce
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp
@@ -0,0 +1,112 @@
+/* -*- 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 "xptiprivate.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
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ 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
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..a4b553940
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp
@@ -0,0 +1,185 @@
+/* -*- 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 "xptiprivate.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_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+#define PARAM_FPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ 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 = &dispatchParams[i];
+
+ 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)
+ dp->val.f = (double)fprData[iCount++];
+ else
+ dp->val.f = *((double*)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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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_netbsd_m68k.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_netbsd_m68k.cpp
new file mode 100644
index 000000000..680114fd5
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_netbsd_m68k.cpp
@@ -0,0 +1,115 @@
+/* -*- 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(__NetBSD__) || !defined(__m68k__)
+#error This code is for NetBSD/m68k only
+#endif
+
+extern "C" {
+ static nsresult ATTRIBUTE_USED
+ PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+ {
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ nsIInterfaceInfo* iface_info = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+
+ switch(type)
+ {
+ // the 8 and 16 bit types will have been promoted to 32 bits before
+ // being pushed onto the stack. Since the 68k is big endian, we
+ // need to skip over the leading high order bytes.
+ case nsXPTType::T_I8 : dp->val.i8 = *(((int8_t*) ap) + 3); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(((int16_t*) ap) + 1); 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) + 3); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(((uint16_t*)ap) + 1); 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 = *(((char*) ap) + 3); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(((char*) ap) + 3); break;
+ // wchar_t is an int (32 bits) on NetBSD
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+ }
+}
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".global _Stub"#n"__14nsXPTCStubBase\n\t" \
+"_Stub"#n"__14nsXPTCStubBase:\n\t" \
+ "link a6,#0 \n\t" \
+ "lea a6@(12), a0 \n\t" /* pointer to args */ \
+ "movl a0, sp@- \n\t" \
+ "movl #"#n", sp@- \n\t" /* method index */ \
+ "movl a6@(8), sp@- \n\t" /* this */ \
+ "jbsr _PrepareAndDispatch \n\t" \
+ "unlk a6 \n\t" \
+ "rts \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_pa32.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp
new file mode 100644
index 000000000..7353709f1
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp
@@ -0,0 +1,143 @@
+
+/* -*- 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 "xptiprivate.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;
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ int32_t regwords = 1; /* self pointer is not in the variant records */
+ nsresult result = NS_ERROR_FAILURE;
+ 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();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for(i = 0; i < paramCount; ++i, --args)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ 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;
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(int);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ return SharedStub(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_ppc64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp
new file mode 100644
index 000000000..95e67cb29
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp
@@ -0,0 +1,246 @@
+/* -*- 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 "xptiprivate.h"
+
+// The Linux/PPC64 ABI passes 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 has to retain 16-byte alignment.
+
+// The PowerPC64 platform ABI can be found here:
+// http://www.freestandards.org/spec/ELF/ppc64/
+// and in particular:
+// http://www.freestandards.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-CALL
+
+#define PARAM_BUFFER_COUNT 16
+#define GPR_COUNT 7
+#define FPR_COUNT 13
+
+// 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.
+#include <stdio.h>
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self,
+ uint64_t methodIndex,
+ uint64_t* args,
+ uint64_t *gprData,
+ double *fprData)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint64_t* ap = args;
+ uint64_t tempu64;
+
+ for(i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (i < FPR_COUNT)
+ dp->val.d = fprData[i];
+ else
+ dp->val.d = *(double*) ap;
+ } else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (i < FPR_COUNT)
+ dp->val.f = (float) fprData[i]; // in registers floats are passed as doubles
+ else {
+ float *p = (float *)ap;
+#ifndef __LITTLE_ENDIAN__
+ p++;
+#endif
+ dp->val.f = *p;
+ }
+ } else { /* integer type or pointer */
+ if (i < GPR_COUNT)
+ tempu64 = gprData[i];
+ else
+ tempu64 = *ap;
+
+ if (param.IsOut() || !type.IsArithmetic())
+ dp->val.p = (void*) tempu64;
+ else if (type == nsXPTType::T_I8)
+ dp->val.i8 = (int8_t) tempu64;
+ else if (type == nsXPTType::T_I16)
+ dp->val.i16 = (int16_t) tempu64;
+ else if (type == nsXPTType::T_I32)
+ dp->val.i32 = (int32_t) tempu64;
+ else if (type == nsXPTType::T_I64)
+ dp->val.i64 = (int64_t) tempu64;
+ else if (type == nsXPTType::T_U8)
+ dp->val.u8 = (uint8_t) tempu64;
+ else if (type == nsXPTType::T_U16)
+ dp->val.u16 = (uint16_t) tempu64;
+ else if (type == nsXPTType::T_U32)
+ dp->val.u32 = (uint32_t) tempu64;
+ else if (type == nsXPTType::T_U64)
+ dp->val.u64 = (uint64_t) tempu64;
+ else if (type == nsXPTType::T_BOOL)
+ dp->val.b = (bool) tempu64;
+ else if (type == nsXPTType::T_CHAR)
+ dp->val.c = (char) tempu64;
+ else if (type == nsXPTType::T_WCHAR)
+ dp->val.wc = (wchar_t) tempu64;
+ else
+ NS_ERROR("bad type");
+ }
+
+ if (i >= 7)
+ ap++;
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info,
+ dispatchParams);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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...
+
+#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 000000000..0463c21c5
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp
@@ -0,0 +1,185 @@
+/* -*- 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"
+#include "xptiprivate.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_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ 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 = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex,info,dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..08eb557ab
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp
@@ -0,0 +1,172 @@
+/* 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 "xptiprivate.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_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ 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 = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex,info,dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..86405a8ca
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp
@@ -0,0 +1,220 @@
+/* -*- 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 "xptiprivate.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 PARAM_BUFFER_COUNT 16
+#define GPR_COUNT 8
+#define FPR_COUNT 8
+#else
+#define PARAM_BUFFER_COUNT 8
+#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];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ 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 = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex,
+ info,
+ dispatchParams);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_netbsd.cpp
new file mode 100644
index 000000000..ec359fc99
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_netbsd.cpp
@@ -0,0 +1,185 @@
+/* -*- 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 PARAM_BUFFER_COUNT 16
+#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];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ nsIInterfaceInfo* iface_info = nullptr;
+ const nsXPTMethodInfo* info;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (! iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (! info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ 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 = &dispatchParams[i];
+
+ 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;
+ if (gpr < GPR_COUNT)
+ gpr += 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;
+ ap += 1;
+ if (gpr < GPR_COUNT)
+ gpr += 1;
+ }
+ 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;
+ }
+ }
+
+ result = self->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 ;-).
+
+#define STUB_ENTRY(n) \
+__asm__ ( \
+ ".section \".text\" \n\t" \
+ ".align 2 \n\t" \
+ ".globl Stub"#n"__14nsXPTCStubBase \n\t" \
+ ".type Stub"#n"__14nsXPTCStubBase,@function \n\n" \
+ \
+"Stub"#n"__14nsXPTCStubBase: \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 000000000..62a693643
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp
@@ -0,0 +1,202 @@
+/* -*- 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 "xptiprivate.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 PARAM_BUFFER_COUNT 16
+#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];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ 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 = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex,
+ info,
+ dispatchParams);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..4c485a275
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp
@@ -0,0 +1,165 @@
+/* -*- 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"
+#include "xptiprivate.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_BUFFER_COUNT 16
+#define PARAM_FPR_COUNT 13
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant *dispatchParams = nullptr;
+ const nsXPTMethodInfo *methodInfo;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+ 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();
+
+ if(paramCount > PARAM_BUFFER_COUNT) {
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ }
+ else {
+ dispatchParams = paramBuffer;
+ }
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ for(i = 0; i < paramCount; i++, argIndex++) {
+ const nsXPTParamInfo &param = methodInfo->GetParam(i);
+ const nsXPTType &type = param.GetType();
+ nsXPTCMiniVariant *dp = &dispatchParams[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;
+ }
+ }
+ }
+
+ result = self->mOuter->
+ CallMethod((uint16_t)methodIndex, methodInfo, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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_sparc64_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp
new file mode 100644
index 000000000..b8a09c97e
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp
@@ -0,0 +1,104 @@
+/* -*- 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"
+#include "xptiprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint64_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp
new file mode 100644
index 000000000..22bf94d49
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp
@@ -0,0 +1,117 @@
+/* -*- 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
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ nsIInterfaceInfo* iface_info = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[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;
+ }
+ }
+
+ result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..55d814b85
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp
@@ -0,0 +1,120 @@
+/* -*- 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
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ nsIInterfaceInfo* iface_info = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[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;
+ }
+ }
+
+ result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..61f3df4ff
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp
@@ -0,0 +1,112 @@
+/* -*- 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 "xptiprivate.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
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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_sparcv9_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparcv9_solaris.cpp
new file mode 100644
index 000000000..583ce9864
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparcv9_solaris.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"
+#include "xptiprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ uint64_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ 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_DOUBLE : dp->val.d = *((double*) ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_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_FLOAT : dp->val.f = ((float*) ap)[1]; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((uint64_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;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..ae058567f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp
@@ -0,0 +1,190 @@
+/* -*- 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"
+#include "xptiprivate.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 PARAM_BUFFER_COUNT = 16;
+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];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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();
+
+ // setup variant array pointer
+ if (paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ 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 = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..01044363b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp
@@ -0,0 +1,204 @@
+/* -*- 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"
+#include "xptiprivate.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 PARAM_BUFFER_COUNT = 16;
+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];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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();
+
+ // setup variant array pointer
+ if (paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ 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 = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+// Linux/x86-64 uses gcc >= 3.1
+#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"
+ // 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@plt\n\t"
+ "leave\n\t"
+ "ret\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/unix/xptcstubs_x86_64_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_solaris.cpp
new file mode 100644
index 000000000..677fa9960
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_solaris.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/. */
+
+// Implement shared vtbl methods.
+
+// Keep this in sync with the darwin version.
+
+#include "xptcprivate.h"
+#include "xptiprivate.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 PARAM_BUFFER_COUNT = 16;
+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];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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();
+
+ // setup variant array pointer
+ if (paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ 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 = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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_x86_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_solaris.cpp
new file mode 100644
index 000000000..39eec5e54
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_solaris.cpp
@@ -0,0 +1,77 @@
+/* -*- 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 "xptiprivate.h"
+
+nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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/win32/moz.build b/xpcom/reflect/xptcall/md/win32/moz.build
new file mode 100644
index 000000000..5dbe41d76
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/moz.build
@@ -0,0 +1,45 @@
+# -*- 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['GNU_CXX']:
+ 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'
+ ]
+else:
+ if CONFIG['GNU_CXX']:
+ SOURCES += [
+ 'xptcinvoke_x86_gnu.cpp',
+ 'xptcstubs.cpp',
+ ]
+ else:
+ SOURCES += [
+ 'xptcinvoke.cpp',
+ 'xptcinvoke_asm_x86_msvc.asm',
+ 'xptcstubs.cpp',
+ ]
+ SOURCES['xptcinvoke.cpp'].no_pgo = True
+ SOURCES['xptcinvoke_asm_x86_msvc.asm'].flags += ['-safeseh']
+
+FINAL_LIBRARY = 'xul'
+
+LOCAL_INCLUDES += [
+ '../..',
+ '/xpcom/reflect/xptinfo',
+]
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp
new file mode 100644
index 000000000..faec869f6
--- /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->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;
+ }
+ }
+}
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 000000000..bf7c2ef0c
--- /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 000000000..006e0444b
--- /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 3
+ .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 000000000..f3b7a1826
--- /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 000000000..36b454b35
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp
@@ -0,0 +1,59 @@
+/* -*- 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->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ 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 000000000..0e73e99f3
--- /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->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"
+
+/*
+ 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 000000000..e525aebd7
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp
@@ -0,0 +1,227 @@
+/* -*- 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 "xptiprivate.h"
+
+#ifndef WIN32
+#error "This code is for Win32 only"
+#endif
+
+extern "C" {
+
+#if !defined(__GNUC__) && !defined(__clang__)
+static
+#endif
+nsresult __stdcall
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint32_t* args, uint32_t* stackBytesToPop)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ // 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();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[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;
+ }
+ }
+ *stackBytesToPop = ((uint32_t)ap) - ((uint32_t)args);
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+} // extern "C"
+
+// declspec(naked) is broken in gcc and clang-cl
+#if !defined(__GNUC__) && !defined(__clang__)
+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 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) \
+__declspec(naked) nsresult __stdcall nsXPTCStubBase::Stub##n() \
+{ __asm mov ecx, n __asm jmp SharedStub }
+
+#else
+
+asm(".text\n\t"
+ ".align 4\n\t"
+ "SharedStub:\n\t"
+ "push %ebp\n\t"
+ "mov %esp, %ebp\n\t"
+ "push %ecx\n\t"
+ "lea -4(%ebp), %eax\n\t"
+ "push %eax\n\t"
+ "lea 12(%ebp), %eax\n\t"
+ "push %eax\n\t"
+ "push %ecx\n\t"
+ "movl 8(%ebp), %eax\n\t"
+ "push %eax\n\t"
+ "call _PrepareAndDispatch@16\n\t"
+ "mov 4(%ebp), %edx\n\t"
+ "mov -4(%ebp), %ecx\n\t"
+ "add $8, %ecx\n\t"
+ "mov %ebp, %esp\n\t"
+ "pop %ebp\n\t"
+ "add %ecx, %esp\n\t"
+ "jmp *%edx"
+);
+
+// The clang-cl specific code below is required because mingw uses the gcc name
+// mangling, but clang-cl implements the MSVC name mangling.
+
+#ifdef __clang__
+
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 4\n\t" \
+ ".globl \"?Stub" #n "@nsXPTCStubBase@@UAG?AW4nsresult@@XZ\"\n\t" \
+ ".def \"?Stub" #n "@nsXPTCStubBase@@UAG?AW4nsresult@@XZ\"; \n\t" \
+ ".scl 2\n\t" \
+ ".type 46\n\t" \
+ ".endef\n\t" \
+ "\"?Stub" #n "@nsXPTCStubBase@@UAG?AW4nsresult@@XZ\":\n\t" \
+ "mov $" #n ", %ecx\n\t" \
+ "jmp SharedStub");
+
+#else
+
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 4\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl __ZN14nsXPTCStubBase5Stub" #n "Ev@4\n\t" \
+ ".def __ZN14nsXPTCStubBase5Stub" #n "Ev@4; \n\t" \
+ ".scl 3\n\t" \
+ ".type 46\n\t" \
+ ".endef\n\t" \
+ "__ZN14nsXPTCStubBase5Stub" #n "Ev@4:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl __ZN14nsXPTCStubBase6Stub" #n "Ev@4\n\t" \
+ ".def __ZN14nsXPTCStubBase6Stub" #n "Ev@4\n\t" \
+ ".scl 3\n\t" \
+ ".type 46\n\t" \
+ ".endef\n\t" \
+ "__ZN14nsXPTCStubBase6Stub" #n "Ev@4:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl __ZN14nsXPTCStubBase7Stub" #n "Ev@4\n\t" \
+ ".def __ZN14nsXPTCStubBase7Stub" #n "Ev@4\n\t" \
+ ".scl 3\n\t" \
+ ".type 46\n\t" \
+ ".endef\n\t" \
+ "__ZN14nsXPTCStubBase7Stub" #n "Ev@4:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "mov $" #n ", %ecx\n\t" \
+ "jmp SharedStub");
+
+#endif
+
+#endif /* __GNUC__ || __clang__ */
+
+#define SENTINEL_ENTRY(n) \
+nsresult __stdcall nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4035) // OK to have no return value
+#endif
+#include "xptcstubsdef.inc"
+#ifdef _MSC_VER
+#pragma warning(default : 4035) // restore default
+#endif
+
+void
+#ifdef __GNUC__
+__cdecl
+#endif
+xptc_dummy()
+{
+}
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 000000000..db2cc16be
--- /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 000000000..8ff479d1e
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp
@@ -0,0 +1,197 @@
+/* -*- 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 "xptiprivate.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)
+{
+#define PARAM_BUFFER_COUNT 16
+//
+// "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];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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
+ //
+
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ 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 = &dispatchParams[i];
+
+ 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 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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 000000000..2676334d2
--- /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"
+#include "xptiprivate.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)
+{
+#define PARAM_BUFFER_COUNT 16
+//
+// "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];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ 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
+ //
+
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ 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 = &dispatchParams[i];
+
+ 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)
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ 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@4\n" \
+ ".def _ZN14nsXPTCStubBase5Stub" #n "Ev@4\n" \
+ ".scl 3\n" /* private */ \
+ ".type 46\n" /* function returning unsigned int */ \
+ ".endef\n" \
+ "_ZN14nsXPTCStubBase5Stub" #n "Ev@4:\n" \
+ ".elseif " #n " < 100\n" \
+ ".globl _ZN14nsXPTCStubBase6Stub" #n "Ev@4\n" \
+ ".def _ZN14nsXPTCStubBase6Stub" #n "Ev@4\n" \
+ ".scl 3\n" /* private */\
+ ".type 46\n" /* function returning unsigned int */ \
+ ".endef\n" \
+ "_ZN14nsXPTCStubBase6Stub" #n "Ev@4:\n" \
+ ".elseif " #n " < 1000\n" \
+ ".globl _ZN14nsXPTCStubBase7Stub" #n "Ev@4\n" \
+ ".def _ZN14nsXPTCStubBase7Stub" #n "Ev@4\n" \
+ ".scl 3\n" /* private */ \
+ ".type 46\n" /* function returning unsigned int */ \
+ ".endef\n" \
+ "_ZN14nsXPTCStubBase7Stub" #n "Ev@4:\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 000000000..fee7a3352
--- /dev/null
+++ b/xpcom/reflect/xptcall/moz.build
@@ -0,0 +1,23 @@
+# -*- 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 += [
+ 'xptcall.h',
+ 'xptcstubsdecl.inc',
+ 'xptcstubsdef.inc',
+]
+
+LOCAL_INCLUDES += [
+ '/xpcom/reflect/xptinfo',
+]
+
+FINAL_LIBRARY = 'xul'
diff --git a/xpcom/reflect/xptcall/porting.html b/xpcom/reflect/xptcall/porting.html
new file mode 100644
index 000000000..0073c604e
--- /dev/null
+++ b/xpcom/reflect/xptcall/porting.html
@@ -0,0 +1,216 @@
+<!-- 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>):
+
+<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>
+
+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>):
+
+<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(nsIInterfaceInfo** 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>
+
+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>
+
+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>
+
+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>
+
+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>
+
+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>
+
+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>
+
+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>
+
+Getting these ports done is very important. Please let <a
+href="mailto:jband@netscape.com">me</a> know if you are interested in doing one.
+I'll answer any questions as I get them.
+
+<p>
+
+<a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/status.html">
+Porting Status
+</a>
+
+</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/status.html b/xpcom/reflect/xptcall/status.html
new file mode 100644
index 000000000..65de20596
--- /dev/null
+++ b/xpcom/reflect/xptcall/status.html
@@ -0,0 +1,412 @@
+<!-- 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 Status</title>
+</head>
+<body bgcolor = "white">
+<h2><center>xptcall Porting Status</center></h2>
+
+<h3>What is this?</h3>
+
+This is a status page for the multiplatform porting of xptcall.
+xptcall has a
+<a href="http://www.mozilla.org/scriptable/xptcall-faq.html">FAQ</a>
+and a
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html">Porting Guide</a>.
+
+<p>
+
+This is being maintained by <a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a>.
+Feel free to email me with questions or to volunteer to contribute xptcall code for any platform.
+
+<p>
+
+<a href="mailto:shaver@mozilla.org">Mike Shaver &lt;shaver@mozilla.org&gt;</a>
+is the best contact regarding 'nix (Unix, Linux, Finux, etc.) ports of xptcall.
+
+<h3>Status</h3>
+
+<table BORDER="1">
+<TR align="left" BGCOLOR="yellow">
+<TH>Status</TH>
+<TH>Platform</TH>
+<TH><img src="http://tinderbox.mozilla.org/star.gif">Contributors and <font color="red"><b>?</b></font> Possible Contributors</TH>
+<TH>Notes</TH>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Win32 x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a>
+</TD>
+<TD>
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32">win32</a></TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a><br>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:drepper@cygnus.com">Ulrich Drepper &lt;drepper@cygnus.com&gt;</a>
+</TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>FreeBSD and NetBSD x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:toshok@hungry.com">Christoph Toshok &lt;toshok@hungry.com&gt;</a>,<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a></TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> (same as Linux 86 code)</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>BSD/OS x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:bert_driehuis@nl.compuware.com">Bert Driehuis &lt;bert_driehuis@nl.compuware.com&gt;</a></TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> (same as Linux 86 code)
+Bert contributed patches that *should* do the right thing for all the unixish-x86
+versions of this code for GCC 2.7 or 2.8 vs. EGCS 1.1. He notes that the vtbl
+scheme is different. He is hoping that others will help test the changes using
+these two compilers on the various platforms where this same code is used.
+<a href="news://news.mozilla.org/372DD257.4248C821%40nl.compuware.com">Bert's details</a>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Mac PPC</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+ <a href="mailto:rogerl@netscape.com">Roger Lawrence &lt;rogerl@netscape.com&gt;</a>,<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:beard@netscape.com">Patrick Beard &lt;beard@netscape.com&gt;</a>
+</TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/mac">mac</a> (passing tests and checked in)</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Solaris Sparc</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:rogerl@netscape.com">Roger Lawrence &lt;rogerl@netscape.com&gt;</a>,<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:mcafee@netscape.com">Chris McAfee &lt;mcafee@netscape.com&gt;</a>
+</TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> This is checked in and working.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Solaris Sparc v9 (64bit)</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:pavlov@netscape.com">Stuart Parmenter &lt;pavlov@netscape.com&gt;</a>,<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:cls@seawood.org">Chris Seawood &lt;cls@seawood.org&gt;</a>
+</TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> This is checked in and (pavlov claims!) working.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>OS/2</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:mjf35@cam.ac.uk">John Fairhurst &lt;mjf35@cam.ac.uk&gt;</a></TD>
+<TD>I never heard exactly who did what. But mozilla has been working on OS/2
+for a long time now.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>OpenVMS Alpha</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:colin@theblakes.com">Colin R. Blake &lt;colin@theblakes.com&gt;</a></TD>
+<TD>
+Colin says this is passing all the tests on OpenVMS Alpha!
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>NT Alpha</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:bob@guiduck.com">bob meader &lt;bob@guiduck.com&gt;</a></TD>
+<TD>
+bob writes:<br>
+Enclosed is xptcall for alpha/nt target..
+<p>
+It is a variation of the IRIS port (only targeted for win32).
+<p>
+Notice the last 2 files (the change to mozilla\xpcom\build\makefile.win and
+mozilla\xpcom\build) are needed because I was unable to figure how to do a
+"declspecexport" from the assembler ASAXP ... if some knows how to do that then
+those last 2 files won't be needed.
+<p>
+I have had someone look over this code at bridge.com (the entry point to
+compaq/gem compiler team) and this code was given the OK. I consider it "done".
+<p>
+This code lives in the files where the name includes 'alpha' in the <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32">win32</a> directory.<BR>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux ARM</TD>
+<TD><img alt="Started" title="Started" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:sh990154@mail.uni-greifswald.de">Stefan Hanske&lt;sh990154@mail.uni-greifswald.de&gt;</a><BR>
+<font color="red"><b>?</b></font>
+<a href="mailto:willy@bofh.ai">Matthew Wilcox &lt;willy@bofh.ai&gt;</a></TD>
+<TD>
+Stefan's code is checked in and he says it is working.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux Sparc</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:anton@progsoc.uts.edu.au">Anton Blanchard &lt;anton@progsoc.uts.edu.au&gt;</a>,
+<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:rogerl@netscape.com">Roger Lawrence &lt;rogerl@netscape.com&gt;</a>,
+<BR>
+<img alt="Maybe" title="Maybe" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:ehle.3@osu.eduehle.3@osu.edu">Brandon Ehle &lt;ehle.3@osu.edu&gt;</a>
+</TD>
+<TD>
+Anton contributed patches to Roger's Sparc code. Anton says it works and passes the tests!<b>
+(24-Aug-1999) Brandon writes: I've finished testing XPTCALL Sparc Linux on 12 different Sparc machines and it checks out good.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux PPC</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:beard@netscape.com">Patrick Beard &lt;beard@netscape.com&gt;</a><BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:waterson@netscape.com">Chris Waterson &lt;waterson@netscape.com&gt;</a><BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:Franz.Sirl-kernel@lauterbach.com">Franz Sirl &lt;Franz.Sirl-kernel@lauterbach.com&gt;</a><BR>
+<font color="red"><b>?</b></font>
+<a href="mailto:jsproul@condor.fddi.wesleyan.edu">Jason Y. Sproul &lt;jsproul@condor.fddi.wesleyan.edu&gt;</a><BR>
+ <font color="red"><b>?</b></font>
+ <a href="mailto:darkmane@w-link.net">Sean Chitwood &lt;darkmane@w-link.net&gt;</a></TD>
+<TD>
+waterson said: <b>Mozilla runs on Linux/PPC</b>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux Alpha</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:glen.nakamura@usa.net">Glen Nakamura &lt;glen.nakamura@usa.net&gt;</a><BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:morrildl@nycap.rr.com">Dan Morril &lt;morrildl@nycap.rr.com&gt;</a><BR>
+</TD>
+<TD>
+Glen writes:
+<p>
+I am attaching a patch which contains my Linux Alpha xptcall code.
+It passes TestXPTCInvoke and TestXPC on my machine which runs
+kernel 2.2.7, glibc 2.1.1, and egcs 1.1.2. I have not tested it
+with older GNU compilers such as gcc 2.8.x. From looking at the
+Linux x86 code, I gather that the vtable layout is a little different
+for those compilers and the code will need minor modifications
+in order to work properly.
+<p>
+I am not sure how much of the code can be used for OpenVMS Alpha
+and/or Digital UNIX. Currently the code is dependent on the g++
+name mangling convention and a few GNU extensions so I'm not sure
+how useful it will be for the other systems. Hopefully the
+comments in the code are detailed enough to help people attempting
+a port.
+<p>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>SunOS x86</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:aljones@lbl.gov">Arthur Jones &lt;aljones@lbl.gov&gt;</a><BR>
+<font color="red"><b>?</b></font>
+<a href="mailto:ppokorny@mindspring.com">Philip Pokorny &lt;ppokorny@mindspring.com&gt;</a><BR>
+</TD>
+<TD>
+The word I hear is that this is working and done
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>HP-UX</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:wang@cup.hp.com">Thomas Wang &lt;wang@cup.hp.com&gt;</a><BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:mgleeson1@netscape.com">Mike Gleeson &lt;mgleeson1@netscape.com&gt;</a>
+</TD>
+<TD>I hear that this code is checked in and working. Though, there is some
+doubt - see bug
+#<a href="http://bugzilla.mozilla.org/show_bug.cgi?id=17997">17997</a>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>AIX PPC</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jdunn@netscape.com">Jim Dunn &lt;jdunn@netscape.com&gt;</a></TD>
+<TD>Philip K. Warren writes: <BR>
+
+We have gone through several releases of AIX without any problems.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Irix</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jasonh@m7.engr.sgi.com">Jason Heirtzler &lt;jasonh@m7.engr.sgi.com&gt;</a><BR>
+</TD>
+<TD>Jason has declared this done. Jason is no longer working at SGI and will
+not be maintaining this code. There is some doubt as to whether or not this is
+working for everyone - see bug
+#<a href="http://bugzilla.mozilla.org/show_bug.cgi?id=10061">10061</a>.
+<a href="mailto:shaver@mozilla.org">Mike&nbsp;Shaver&nbsp;&lt;shaver@mozilla.org&gt;</a>
+is the interim maintainer until someone more suitable can be found.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>BeOS x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:duncan@be.com">Duncan Wilcox &lt;duncan@be.com&gt;</a><BR>
+</TD>
+<TD>
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> (yet another reuse of the Linux 86 code!)<BR>
+Duncan says this is all working. He did the code for old cfront style 'this' adjustment for others to use too!
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="red"><font color="white"><b>HELP!</b></font></TD>
+<TD>BeOS PPC</TD>
+<TD align="center">-</TD>
+<TD align="center">-</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Compaq Tru64 UNIX (Digital UNIX)</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:streeter@zk3.dec.com">Steve Streeter &lt;streeter@zk3.dec.com&gt;</a><BR>
+</TD>
+<TD>Code passes the tests and is checked in.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="khaki"><font color="black"><b>Working</b></font></TD>
+<TD>Neutrio x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:Jerry.Kirk@Nexwarecorp.com">Jerry L. Kirk &lt;Jerry.Kirk@Nexwarecorp.com&gt;</a><BR>
+</TD>
+<TD>
+Patches for xptc*_unixish_x86.cpp checked in. Waiting for verification that this is really finished.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="khaki"><font color="black"><b>Investigating</b></font></TD>
+<TD>SCO UW7 and OSR5</TD>
+<TD>
+<img alt="Investigating" title="Investigating" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jkj@sco.com">J. Kean Johnston &lt;jkj@sco.com&gt;</a><BR>
+<img alt="Investigating" title="Investigating" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:evanh@sco.com">Evan Hunt &lt;evanh@sco.com&gt;</a><BR>
+</TD>
+<TD>Recent (Feb-2001) email from jkj@sco.com suggests that work will be occuring soon.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="khaki"><font color="black"><b>Works</b></font></TD>
+<TD>NetBSD/m68k</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:khym@bga.com">Dave Huang &lt;khym@bga.com&gt;</a><BR>
+</TD>
+<TD>
+Dave's changes are in the tree. Waiting for verification that it is really finished.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="khaki"><font color="black"><b>Partially Working</b></font></TD>
+<TD>NetBSD/arm32</TD>
+<TD><img alt="Investigating" title="Investigating" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:mpumford@black-star.demon.co.uk">Mike Pumford &lt;mpumford@black-star.demon.co.uk&gt;</a>
+</TD>
+<TD>Mike writes:<BR>
+I have started porting to the platform based on the code for Linux ARM. The
+InvokeByIndex code works correctly when used with TestXPTCInvoke. I am
+currently working on making TestXPC function correctly.
+<P>
+I am doing the porting work with egcs-1.1.2 on NetBSD 1.4P (NetBSD-current
+snapshot from a couple of days ago).
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux ia64</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+HP<br>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:drepper@redhat.com">Ulrich Drepper &lt;drepper@redhat.com&gt;</a>
+</TD>
+<TD><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=40950#c15">bug 40950 comment 15</a></TD>
+</TR>
+
+
+<TR>
+<TD bgcolor="red"><font color="white"><b>HELP!</b></font></TD>
+<TD>All others!</TD>
+<TD align="center">-</TD>
+<TD align="center">-</TD>
+</TR>
+
+
+</table>
+
+<p>
+
+<b>Note:</b> I've used the symbol (<font color="red"><b>?</b></font>) to
+indicate people who have expressed an interest in <i>possibly</i> contributing code.
+Just because these people are listed here does not mean that they have commited
+themselves to do the work. If <b>you</b> would like to contribute then let me
+know. Feel free to email these folks and offer to help or find out what's going
+on. We're all in this together.
+
+<p>
+
+<hr>
+<b>Author:</b> <a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a><br>
+<b>Last modified:</b> 3 February 2003
+
+</body>
+</html>
diff --git a/xpcom/reflect/xptcall/xptcall.cpp b/xpcom/reflect/xptcall/xptcall.cpp
new file mode 100644
index 000000000..1ea0ac34d
--- /dev/null
+++ b/xpcom/reflect/xptcall/xptcall.cpp
@@ -0,0 +1,82 @@
+/* -*- 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/. */
+
+/* entry point wrappers. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+#include "mozilla/XPTInterfaceInfoManager.h"
+#include "nsPrintfCString.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;
+
+ XPTInterfaceInfoManager *iim =
+ XPTInterfaceInfoManager::GetSingleton();
+ if (NS_WARN_IF(!iim))
+ return NS_ERROR_NOT_INITIALIZED;
+
+ xptiInterfaceEntry *iie = iim->GetInterfaceEntryForIID(&aIID);
+ if (!iie || !iie->EnsureResolved() || iie->GetBuiltinClassFlag())
+ return NS_ERROR_FAILURE;
+
+ if (iie->GetHasNotXPCOMFlag()) {
+#ifdef DEBUG
+ nsPrintfCString msg("XPTCall will not implement interface %s because of [notxpcom] members.", iie->GetTheName());
+ NS_WARNING(msg.get());
+#endif
+ 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 000000000..1f2367b5d
--- /dev/null
+++ b/xpcom/reflect/xptcall/xptcall.h
@@ -0,0 +1,193 @@
+/* -*- 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/. */
+
+/* Public declarations for xptcall. */
+
+#ifndef xptcall_h___
+#define xptcall_h___
+
+#include "nscore.h"
+#include "nsISupports.h"
+#include "xpt_struct.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
+ {
+ 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;
+
+ // Types below here are unknown to the assembly implementations, and
+ // therefore _must_ be passed with indirect semantics. We put them in
+ // the union here for type safety, so that we can avoid void* tricks.
+ JS::Value j;
+ } val;
+};
+
+struct nsXPTCVariant : public nsXPTCMiniVariant
+{
+// No ctors or dtors so that we can use arrays of these on the stack
+// with no penalty.
+
+ // inherits 'val' here
+ void* ptr;
+ nsXPTType type;
+ uint8_t flags;
+
+ enum
+ {
+ //
+ // Bitflag definitions
+ //
+
+ // Indicates that ptr (above, and distinct from val.p) is the value that
+ // should be passed on the stack.
+ //
+ // In theory, ptr could point anywhere. But in practice it always points
+ // to &val. So this flag is used to pass 'val' by reference, letting us
+ // avoid the extra allocation we would incur if we were to use val.p.
+ //
+ // Various parts of XPConnect assume that ptr==&val, so we enforce it
+ // explicitly with SetIndirect() and IsIndirect().
+ //
+ // Since ptr always points to &val, the semantics of this flag are kind of
+ // dumb, since the ptr field is unnecessary. But changing them would
+ // require changing dozens of assembly files, so they're likely to stay
+ // the way they are.
+ PTR_IS_DATA = 0x1,
+
+ // Indicates that the value we hold requires some sort of cleanup (memory
+ // deallocation, interface release, JS::Value unrooting, etc). The precise
+ // cleanup that is performed depends on the 'type' field above.
+ // If the value is an array, this flag specifies whether the elements
+ // within the array require cleanup (we always clean up the array itself,
+ // so this flag would be redundant for that purpose).
+ VAL_NEEDS_CLEANUP = 0x2
+ };
+
+ void ClearFlags() {flags = 0;}
+ void SetIndirect() {ptr = &val; flags |= PTR_IS_DATA;}
+ void SetValNeedsCleanup() {flags |= VAL_NEEDS_CLEANUP;}
+
+ bool IsIndirect() const {return 0 != (flags & PTR_IS_DATA);}
+ bool DoesValNeedCleanup() const {return 0 != (flags & VAL_NEEDS_CLEANUP);}
+
+ // Internal use only. Use IsIndirect() instead.
+ bool IsPtrData() const {return 0 != (flags & PTR_IS_DATA);}
+
+ void Init(const nsXPTCMiniVariant& mv, const nsXPTType& t, uint8_t f)
+ {
+ type = t;
+ flags = f;
+
+ if(f & PTR_IS_DATA)
+ {
+ ptr = mv.val.p;
+ val.p = nullptr;
+ }
+ else
+ {
+ ptr = nullptr;
+ val.p = nullptr; // make sure 'val.p' is always initialized
+ switch(t.TagPart()) {
+ case nsXPTType::T_I8: val.i8 = mv.val.i8; break;
+ case nsXPTType::T_I16: val.i16 = mv.val.i16; break;
+ case nsXPTType::T_I32: val.i32 = mv.val.i32; break;
+ case nsXPTType::T_I64: val.i64 = mv.val.i64; break;
+ case nsXPTType::T_U8: val.u8 = mv.val.u8; break;
+ case nsXPTType::T_U16: val.u16 = mv.val.u16; break;
+ case nsXPTType::T_U32: val.u32 = mv.val.u32; break;
+ case nsXPTType::T_U64: val.u64 = mv.val.u64; break;
+ case nsXPTType::T_FLOAT: val.f = mv.val.f; break;
+ case nsXPTType::T_DOUBLE: val.d = mv.val.d; break;
+ case nsXPTType::T_BOOL: val.b = mv.val.b; break;
+ case nsXPTType::T_CHAR: val.c = mv.val.c; break;
+ case nsXPTType::T_WCHAR: val.wc = mv.val.wc; break;
+ case nsXPTType::T_VOID: /* fall through */
+ case nsXPTType::T_IID: /* fall through */
+ case nsXPTType::T_DOMSTRING: /* fall through */
+ case nsXPTType::T_CHAR_STR: /* fall through */
+ case nsXPTType::T_WCHAR_STR: /* fall through */
+ case nsXPTType::T_INTERFACE: /* fall through */
+ case nsXPTType::T_INTERFACE_IS: /* fall through */
+ case nsXPTType::T_ARRAY: /* fall through */
+ case nsXPTType::T_PSTRING_SIZE_IS: /* fall through */
+ case nsXPTType::T_PWSTRING_SIZE_IS: /* fall through */
+ case nsXPTType::T_UTF8STRING: /* fall through */
+ case nsXPTType::T_CSTRING: /* fall through */
+ default: val.p = mv.val.p; break;
+ }
+ }
+ }
+};
+
+class nsIXPTCProxy : public nsISupports
+{
+public:
+ NS_IMETHOD CallMethod(uint16_t aMethodIndex,
+ const XPTMethodDescriptor *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);
+
+XPCOM_API(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 000000000..7805792e7
--- /dev/null
+++ b/xpcom/reflect/xptcall/xptcprivate.h
@@ -0,0 +1,67 @@
+/* -*- 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/. */
+
+/* All the xptcall private declarations - only include locally. */
+
+#ifndef xptcprivate_h___
+#define xptcprivate_h___
+
+#include "xptcall.h"
+#include "nsAutoPtr.h"
+#include "mozilla/Attributes.h"
+
+class xptiInterfaceEntry;
+
+#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, xptiInterfaceEntry *aEntry)
+ : mOuter(aOuter), mEntry(aEntry) { MOZ_COUNT_CTOR(nsXPTCStubBase); }
+
+ nsIXPTCProxy* mOuter;
+ xptiInterfaceEntry* mEntry;
+
+ ~nsXPTCStubBase() { MOZ_COUNT_DTOR(nsXPTCStubBase); }
+};
+
+#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 000000000..91d35fe32
--- /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 000000000..2df455406
--- /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/ShimInterfaceInfo.cpp b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
new file mode 100644
index 000000000..14e719f6c
--- /dev/null
+++ b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
@@ -0,0 +1,700 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * 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 "ShimInterfaceInfo.h"
+
+#include "nsIBrowserBoxObject.h"
+#include "nsIContainerBoxObject.h"
+#include "nsIDOMAnimationEvent.h"
+#include "nsIDOMAttr.h"
+#include "nsIDOMBeforeUnloadEvent.h"
+#include "nsIDOMCanvasRenderingContext2D.h"
+#include "nsIDOMCDATASection.h"
+#include "nsIDOMCharacterData.h"
+#include "nsIDOMClientRect.h"
+#include "nsIDOMClientRectList.h"
+#include "nsIDOMClipboardEvent.h"
+#include "nsIDOMCommandEvent.h"
+#include "nsIDOMComment.h"
+#include "nsIDOMCSSPrimitiveValue.h"
+#include "nsIDOMCSSStyleDeclaration.h"
+#include "nsIDOMCSSStyleSheet.h"
+#include "nsIDOMCSSValue.h"
+#include "nsIDOMCSSValueList.h"
+#include "nsIDOMCustomEvent.h"
+#include "nsIDOMDataContainerEvent.h"
+#ifdef MOZ_WEBRTC
+#include "nsIDOMDataChannel.h"
+#endif
+#include "nsIDOMDataTransfer.h"
+#include "nsIDOMDOMCursor.h"
+#include "nsIDOMDOMException.h"
+#include "nsIDOMDOMRequest.h"
+#include "nsIDOMDocument.h"
+#include "nsIDOMDocumentFragment.h"
+#include "nsIDOMDocumentType.h"
+#include "nsIDOMDocumentXBL.h"
+#include "nsIDOMDragEvent.h"
+#include "nsIDOMElement.h"
+#include "nsIDOMEvent.h"
+#include "nsIDOMEventTarget.h"
+#include "nsIDOMFileList.h"
+#include "nsIDOMFocusEvent.h"
+#include "nsIDOMFormData.h"
+#include "nsIDOMGeoPositionError.h"
+#include "nsIDOMHistory.h"
+#include "nsIDOMHTMLAnchorElement.h"
+#include "nsIDOMHTMLAppletElement.h"
+#include "nsIDOMHTMLAreaElement.h"
+#include "nsIDOMHTMLBaseElement.h"
+#include "nsIDOMHTMLBodyElement.h"
+#include "nsIDOMHTMLButtonElement.h"
+#include "nsIDOMHTMLCanvasElement.h"
+#include "nsIDOMHTMLCollection.h"
+#include "nsIDOMHTMLDirectoryElement.h"
+#include "nsIDOMHTMLDocument.h"
+#include "nsIDOMHTMLElement.h"
+#include "nsIDOMHTMLEmbedElement.h"
+#include "nsIDOMHTMLFieldSetElement.h"
+#include "nsIDOMHTMLFormElement.h"
+#include "nsIDOMHTMLFrameElement.h"
+#include "nsIDOMHTMLFrameSetElement.h"
+#include "nsIDOMHTMLHRElement.h"
+#include "nsIDOMHTMLHeadElement.h"
+#include "nsIDOMHTMLHtmlElement.h"
+#include "nsIDOMHTMLIFrameElement.h"
+#include "nsIDOMHTMLImageElement.h"
+#include "nsIDOMHTMLInputElement.h"
+#include "nsIDOMHTMLLIElement.h"
+#include "nsIDOMHTMLLabelElement.h"
+#include "nsIDOMHTMLLinkElement.h"
+#include "nsIDOMHTMLMapElement.h"
+#include "nsIDOMHTMLMediaElement.h"
+#include "nsIDOMHTMLMenuElement.h"
+#include "nsIDOMHTMLMenuItemElement.h"
+#include "nsIDOMHTMLMetaElement.h"
+#include "nsIDOMHTMLOListElement.h"
+#include "nsIDOMHTMLObjectElement.h"
+#include "nsIDOMHTMLOptGroupElement.h"
+#include "nsIDOMHTMLOptionElement.h"
+#include "nsIDOMHTMLOptionsCollection.h"
+#include "nsIDOMHTMLParagraphElement.h"
+#include "nsIDOMHTMLPreElement.h"
+#include "nsIDOMHTMLQuoteElement.h"
+#include "nsIDOMHTMLScriptElement.h"
+#include "nsIDOMHTMLSelectElement.h"
+#include "nsIDOMHTMLSourceElement.h"
+#include "nsIDOMHTMLStyleElement.h"
+#include "nsIDOMHTMLTableCellElement.h"
+#include "nsIDOMHTMLTextAreaElement.h"
+#include "nsIDOMHTMLUListElement.h"
+#include "nsIDOMKeyEvent.h"
+#include "nsIDOMMediaList.h"
+#include "nsIDOMMouseEvent.h"
+#include "nsIDOMMouseScrollEvent.h"
+#include "nsIDOMMutationEvent.h"
+#include "nsIDOMMozNamedAttrMap.h"
+#include "nsIDOMNode.h"
+#include "nsIDOMNodeIterator.h"
+#include "nsIDOMNotifyPaintEvent.h"
+#include "nsIDOMNSEvent.h"
+#include "nsIDOMOfflineResourceList.h"
+#include "nsIDOMPaintRequest.h"
+#include "nsIDOMParser.h"
+#include "nsIDOMProcessingInstruction.h"
+#include "nsIDOMRange.h"
+#include "nsIDOMRect.h"
+#include "nsIDOMScreen.h"
+#include "nsIDOMScrollAreaEvent.h"
+#include "nsIDOMSerializer.h"
+#include "nsIDOMSimpleGestureEvent.h"
+#include "nsIDOMStyleSheet.h"
+#include "nsIDOMStyleSheetList.h"
+#include "nsIDOMSVGElement.h"
+#include "nsIDOMSVGLength.h"
+#include "nsIDOMText.h"
+#include "nsIDOMTimeEvent.h"
+#include "nsIDOMTimeRanges.h"
+#include "nsIDOMTransitionEvent.h"
+#include "nsIDOMTreeWalker.h"
+#include "nsIDOMUIEvent.h"
+#include "nsIDOMValidityState.h"
+#include "nsIDOMWheelEvent.h"
+#include "nsIDOMXMLDocument.h"
+#include "nsIDOMXPathEvaluator.h"
+#include "nsIDOMXPathResult.h"
+#include "nsIDOMXULCommandEvent.h"
+#include "nsIDOMXULDocument.h"
+#include "nsIDOMXULElement.h"
+#include "nsIListBoxObject.h"
+#include "nsIMenuBoxObject.h"
+#include "nsIScrollBoxObject.h"
+#include "nsISelection.h"
+#include "nsITreeBoxObject.h"
+#include "nsIXMLHttpRequest.h"
+
+#include "mozilla/dom/AnimationEventBinding.h"
+#include "mozilla/dom/AttrBinding.h"
+#include "mozilla/dom/BeforeUnloadEventBinding.h"
+#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
+#include "mozilla/dom/CDATASectionBinding.h"
+#include "mozilla/dom/CharacterDataBinding.h"
+#include "mozilla/dom/DOMRectBinding.h"
+#include "mozilla/dom/DOMRectListBinding.h"
+#include "mozilla/dom/ClipboardEventBinding.h"
+#include "mozilla/dom/CommandEventBinding.h"
+#include "mozilla/dom/CommentBinding.h"
+#include "mozilla/dom/ContainerBoxObjectBinding.h"
+#include "mozilla/dom/CSSPrimitiveValueBinding.h"
+#include "mozilla/dom/CSSStyleDeclarationBinding.h"
+#include "mozilla/dom/CSSStyleSheetBinding.h"
+#include "mozilla/dom/CSSValueBinding.h"
+#include "mozilla/dom/CSSValueListBinding.h"
+#include "mozilla/dom/CustomEventBinding.h"
+#ifdef MOZ_WEBRTC
+#include "mozilla/dom/DataChannelBinding.h"
+#endif
+#include "mozilla/dom/DataContainerEventBinding.h"
+#include "mozilla/dom/DataTransferBinding.h"
+#include "mozilla/dom/DOMCursorBinding.h"
+#include "mozilla/dom/DOMExceptionBinding.h"
+#include "mozilla/dom/DOMParserBinding.h"
+#include "mozilla/dom/DOMRequestBinding.h"
+#include "mozilla/dom/DocumentBinding.h"
+#include "mozilla/dom/DocumentFragmentBinding.h"
+#include "mozilla/dom/DocumentTypeBinding.h"
+#include "mozilla/dom/DocumentBinding.h"
+#include "mozilla/dom/DragEventBinding.h"
+#include "mozilla/dom/ElementBinding.h"
+#include "mozilla/dom/EventBinding.h"
+#include "mozilla/dom/EventTargetBinding.h"
+#include "mozilla/dom/FileListBinding.h"
+#include "mozilla/dom/FocusEventBinding.h"
+#include "mozilla/dom/FormDataBinding.h"
+#include "mozilla/dom/HistoryBinding.h"
+#include "mozilla/dom/HTMLAnchorElementBinding.h"
+#include "mozilla/dom/HTMLAppletElementBinding.h"
+#include "mozilla/dom/HTMLAreaElementBinding.h"
+#include "mozilla/dom/HTMLBaseElementBinding.h"
+#include "mozilla/dom/HTMLBodyElementBinding.h"
+#include "mozilla/dom/HTMLButtonElementBinding.h"
+#include "mozilla/dom/HTMLCanvasElementBinding.h"
+#include "mozilla/dom/HTMLCollectionBinding.h"
+#include "mozilla/dom/HTMLDirectoryElementBinding.h"
+#include "mozilla/dom/HTMLDocumentBinding.h"
+#include "mozilla/dom/HTMLElementBinding.h"
+#include "mozilla/dom/HTMLEmbedElementBinding.h"
+#include "mozilla/dom/HTMLFieldSetElementBinding.h"
+#include "mozilla/dom/HTMLFormElementBinding.h"
+#include "mozilla/dom/HTMLFrameElementBinding.h"
+#include "mozilla/dom/HTMLFrameSetElementBinding.h"
+#include "mozilla/dom/HTMLHRElementBinding.h"
+#include "mozilla/dom/HTMLHeadElementBinding.h"
+#include "mozilla/dom/HTMLHtmlElementBinding.h"
+#include "mozilla/dom/HTMLIFrameElementBinding.h"
+#include "mozilla/dom/HTMLImageElementBinding.h"
+#include "mozilla/dom/HTMLInputElementBinding.h"
+#include "mozilla/dom/HTMLLIElementBinding.h"
+#include "mozilla/dom/HTMLLabelElementBinding.h"
+#include "mozilla/dom/HTMLLinkElementBinding.h"
+#include "mozilla/dom/HTMLMapElementBinding.h"
+#include "mozilla/dom/HTMLMediaElementBinding.h"
+#include "mozilla/dom/HTMLMenuElementBinding.h"
+#include "mozilla/dom/HTMLMenuItemElementBinding.h"
+#include "mozilla/dom/HTMLMetaElementBinding.h"
+#include "mozilla/dom/HTMLOListElementBinding.h"
+#include "mozilla/dom/HTMLObjectElementBinding.h"
+#include "mozilla/dom/HTMLOptGroupElementBinding.h"
+#include "mozilla/dom/HTMLOptionElementBinding.h"
+#include "mozilla/dom/HTMLOptionsCollectionBinding.h"
+#include "mozilla/dom/HTMLParagraphElementBinding.h"
+#include "mozilla/dom/HTMLPreElementBinding.h"
+#include "mozilla/dom/HTMLQuoteElementBinding.h"
+#include "mozilla/dom/HTMLScriptElementBinding.h"
+#include "mozilla/dom/HTMLSelectElementBinding.h"
+#include "mozilla/dom/HTMLSourceElementBinding.h"
+#include "mozilla/dom/HTMLStyleElementBinding.h"
+#include "mozilla/dom/HTMLTableCellElementBinding.h"
+#include "mozilla/dom/HTMLTextAreaElementBinding.h"
+#include "mozilla/dom/HTMLUListElementBinding.h"
+#include "mozilla/dom/KeyEventBinding.h"
+#include "mozilla/dom/ListBoxObjectBinding.h"
+#include "mozilla/dom/MediaListBinding.h"
+#include "mozilla/dom/MessageEventBinding.h"
+#include "mozilla/dom/MenuBoxObjectBinding.h"
+#include "mozilla/dom/MouseEventBinding.h"
+#include "mozilla/dom/MouseScrollEventBinding.h"
+#include "mozilla/dom/MutationEventBinding.h"
+#include "mozilla/dom/NamedNodeMapBinding.h"
+#include "mozilla/dom/NodeIteratorBinding.h"
+#include "mozilla/dom/NodeBinding.h"
+#include "mozilla/dom/NotifyPaintEventBinding.h"
+#include "mozilla/dom/EventBinding.h"
+#include "mozilla/dom/OfflineResourceListBinding.h"
+#include "mozilla/dom/PaintRequestBinding.h"
+#include "mozilla/dom/PositionErrorBinding.h"
+#include "mozilla/dom/ProcessingInstructionBinding.h"
+#include "mozilla/dom/RangeBinding.h"
+#include "mozilla/dom/RectBinding.h"
+#include "mozilla/dom/ScreenBinding.h"
+#include "mozilla/dom/ScrollBoxObjectBinding.h"
+#include "mozilla/dom/SelectionBinding.h"
+#include "mozilla/dom/ScrollAreaEventBinding.h"
+#include "mozilla/dom/SimpleGestureEventBinding.h"
+#include "mozilla/dom/StorageEventBinding.h"
+#include "mozilla/dom/StyleSheetBinding.h"
+#include "mozilla/dom/StyleSheetListBinding.h"
+#include "mozilla/dom/SVGElementBinding.h"
+#include "mozilla/dom/SVGLengthBinding.h"
+#include "mozilla/dom/TextBinding.h"
+#include "mozilla/dom/TimeEventBinding.h"
+#include "mozilla/dom/TimeRangesBinding.h"
+#include "mozilla/dom/TransitionEventBinding.h"
+#include "mozilla/dom/TreeBoxObjectBinding.h"
+#include "mozilla/dom/TreeWalkerBinding.h"
+#include "mozilla/dom/UIEventBinding.h"
+#include "mozilla/dom/ValidityStateBinding.h"
+#include "mozilla/dom/WheelEventBinding.h"
+#include "mozilla/dom/XMLDocumentBinding.h"
+#include "mozilla/dom/XMLHttpRequestEventTargetBinding.h"
+#include "mozilla/dom/XMLHttpRequestUploadBinding.h"
+#include "mozilla/dom/XMLSerializerBinding.h"
+#include "mozilla/dom/XPathEvaluatorBinding.h"
+#include "mozilla/dom/XPathResultBinding.h"
+#include "mozilla/dom/XULCommandEventBinding.h"
+#include "mozilla/dom/XULDocumentBinding.h"
+#include "mozilla/dom/XULElementBinding.h"
+
+using namespace mozilla;
+
+struct ComponentsInterfaceShimEntry {
+ constexpr
+ ComponentsInterfaceShimEntry(const char* aName, const nsIID& aIID,
+ const dom::NativePropertyHooks* aNativePropHooks)
+ : geckoName(aName), iid(aIID), nativePropHooks(aNativePropHooks) {}
+
+ const char *geckoName;
+ const nsIID& iid;
+ const dom::NativePropertyHooks* nativePropHooks;
+};
+
+#define DEFINE_SHIM_WITH_CUSTOM_INTERFACE(geckoName, domName) \
+ { #geckoName, NS_GET_IID(geckoName), \
+ mozilla::dom::domName ## Binding::sNativePropertyHooks }
+#define DEFINE_SHIM(name) \
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOM ## name, name)
+
+/**
+ * These shim entries allow us to make old XPIDL interfaces implementing DOM
+ * APIs as non-scriptable in order to save some runtime memory on Firefox OS,
+ * without breaking the entries under Components.interfaces which might both
+ * be used by our code and add-ons. Specifically, the shim entries provide
+ * the following:
+ *
+ * * Components.interfaces.nsIFoo entries. These entries basically work
+ * almost exactly as the usual ones that you would get through the
+ * XPIDL machinery. Specifically, they have the right name, they reflect
+ * the right IID, and they will work properly when passed to QueryInterface.
+ *
+ * * Components.interfaces.nsIFoo.CONSTANT values. These entries will have
+ * the right name and the right value for most integer types. Note that
+ * support for non-numerical constants is untested and will probably not
+ * work out of the box.
+ *
+ * FAQ:
+ * * When should I add an entry to the list here?
+ * Only if you're making an XPIDL interfaces which has a corresponding
+ * WebIDL interface non-scriptable.
+ * * When should I remove an entry from this list?
+ * If you are completely removing an XPIDL interface from the code base. If
+ * you forget to do so, the compiler will remind you.
+ * * How should I add an entry to the list here?
+ * First, make sure that the XPIDL interface in question is non-scriptable
+ * and also has a corresponding WebIDL interface. Then, add two include
+ * entries above, one for the XPIDL interface and one for the WebIDL
+ * interface, and add a shim entry below. If the name of the XPIDL
+ * interface only has an "nsIDOM" prefix prepended to the WebIDL name, you
+ * can use the DEFINE_SHIM macro and pass in the name of the WebIDL
+ * interface. Otherwise, use DEFINE_SHIM_WITH_CUSTOM_INTERFACE.
+ */
+
+const ComponentsInterfaceShimEntry kComponentsInterfaceShimMap[] =
+{
+ DEFINE_SHIM(AnimationEvent),
+ DEFINE_SHIM(Attr),
+ DEFINE_SHIM(BeforeUnloadEvent),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIBrowserBoxObject, ContainerBoxObject),
+ DEFINE_SHIM(CanvasRenderingContext2D),
+ DEFINE_SHIM(CDATASection),
+ DEFINE_SHIM(CharacterData),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMClientRect, DOMRectReadOnly),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMClientRectList, DOMRectList),
+ DEFINE_SHIM(ClipboardEvent),
+ DEFINE_SHIM(CommandEvent),
+ DEFINE_SHIM(Comment),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIContainerBoxObject, ContainerBoxObject),
+ DEFINE_SHIM(CSSPrimitiveValue),
+ DEFINE_SHIM(CSSStyleDeclaration),
+ DEFINE_SHIM(CSSStyleSheet),
+ DEFINE_SHIM(CSSValue),
+ DEFINE_SHIM(CSSValueList),
+ DEFINE_SHIM(CustomEvent),
+#ifdef MOZ_WEBRTC
+ DEFINE_SHIM(DataChannel),
+#endif
+ DEFINE_SHIM(DataContainerEvent),
+ DEFINE_SHIM(DataTransfer),
+ DEFINE_SHIM(DOMCursor),
+ DEFINE_SHIM(DOMException),
+ DEFINE_SHIM(DOMRequest),
+ DEFINE_SHIM(Document),
+ DEFINE_SHIM(DocumentFragment),
+ DEFINE_SHIM(DocumentType),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMDocumentXBL, Document),
+ DEFINE_SHIM(DragEvent),
+ DEFINE_SHIM(Element),
+ DEFINE_SHIM(Event),
+ DEFINE_SHIM(EventTarget),
+ DEFINE_SHIM(FileList),
+ DEFINE_SHIM(FocusEvent),
+ DEFINE_SHIM(FormData),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMGeoPositionError, PositionError),
+ DEFINE_SHIM(History),
+ DEFINE_SHIM(HTMLAnchorElement),
+ DEFINE_SHIM(HTMLAppletElement),
+ DEFINE_SHIM(HTMLAreaElement),
+ DEFINE_SHIM(HTMLBaseElement),
+ DEFINE_SHIM(HTMLBodyElement),
+ DEFINE_SHIM(HTMLButtonElement),
+ DEFINE_SHIM(HTMLCanvasElement),
+ DEFINE_SHIM(HTMLCollection),
+ DEFINE_SHIM(HTMLDirectoryElement),
+ DEFINE_SHIM(HTMLDocument),
+ DEFINE_SHIM(HTMLElement),
+ DEFINE_SHIM(HTMLEmbedElement),
+ DEFINE_SHIM(HTMLFieldSetElement),
+ DEFINE_SHIM(HTMLFormElement),
+ DEFINE_SHIM(HTMLFrameElement),
+ DEFINE_SHIM(HTMLFrameSetElement),
+ DEFINE_SHIM(HTMLHRElement),
+ DEFINE_SHIM(HTMLHeadElement),
+ DEFINE_SHIM(HTMLHtmlElement),
+ DEFINE_SHIM(HTMLIFrameElement),
+ DEFINE_SHIM(HTMLImageElement),
+ DEFINE_SHIM(HTMLInputElement),
+ DEFINE_SHIM(HTMLLIElement),
+ DEFINE_SHIM(HTMLLabelElement),
+ DEFINE_SHIM(HTMLLinkElement),
+ DEFINE_SHIM(HTMLMapElement),
+ DEFINE_SHIM(HTMLMediaElement),
+ DEFINE_SHIM(HTMLMenuElement),
+ DEFINE_SHIM(HTMLMenuItemElement),
+ DEFINE_SHIM(HTMLMetaElement),
+ DEFINE_SHIM(HTMLOListElement),
+ DEFINE_SHIM(HTMLObjectElement),
+ DEFINE_SHIM(HTMLOptGroupElement),
+ DEFINE_SHIM(HTMLOptionElement),
+ DEFINE_SHIM(HTMLOptionsCollection),
+ DEFINE_SHIM(HTMLParagraphElement),
+ DEFINE_SHIM(HTMLPreElement),
+ DEFINE_SHIM(HTMLQuoteElement),
+ DEFINE_SHIM(HTMLScriptElement),
+ DEFINE_SHIM(HTMLSelectElement),
+ DEFINE_SHIM(HTMLSourceElement),
+ DEFINE_SHIM(HTMLStyleElement),
+ DEFINE_SHIM(HTMLTableCellElement),
+ DEFINE_SHIM(HTMLTextAreaElement),
+ DEFINE_SHIM(HTMLUListElement),
+ DEFINE_SHIM(KeyEvent),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIListBoxObject, ListBoxObject),
+ DEFINE_SHIM(MediaList),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIMenuBoxObject, MenuBoxObject),
+ DEFINE_SHIM(MouseEvent),
+ DEFINE_SHIM(MouseScrollEvent),
+ DEFINE_SHIM(MutationEvent),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMMozNamedAttrMap, NamedNodeMap),
+ DEFINE_SHIM(NodeIterator),
+ DEFINE_SHIM(Node),
+ DEFINE_SHIM(NotifyPaintEvent),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMNSEvent, Event),
+ DEFINE_SHIM(OfflineResourceList),
+ DEFINE_SHIM(PaintRequest),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMParser, DOMParser),
+ DEFINE_SHIM(ProcessingInstruction),
+ DEFINE_SHIM(Range),
+ DEFINE_SHIM(Rect),
+ DEFINE_SHIM(Screen),
+ DEFINE_SHIM(ScrollAreaEvent),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIScrollBoxObject, ScrollBoxObject),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMSerializer, XMLSerializer),
+ DEFINE_SHIM(SimpleGestureEvent),
+ DEFINE_SHIM(StyleSheet),
+ DEFINE_SHIM(StyleSheetList),
+ DEFINE_SHIM(SVGElement),
+ DEFINE_SHIM(SVGLength),
+ DEFINE_SHIM(Text),
+ DEFINE_SHIM(TimeEvent),
+ DEFINE_SHIM(TimeRanges),
+ DEFINE_SHIM(TransitionEvent),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsITreeBoxObject, TreeBoxObject),
+ DEFINE_SHIM(TreeWalker),
+ DEFINE_SHIM(UIEvent),
+ DEFINE_SHIM(ValidityState),
+ DEFINE_SHIM(WheelEvent),
+ DEFINE_SHIM(XMLDocument),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIXMLHttpRequestEventTarget, XMLHttpRequestEventTarget),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIXMLHttpRequestUpload, XMLHttpRequestUpload),
+ DEFINE_SHIM(XPathEvaluator),
+ DEFINE_SHIM(XPathResult),
+ DEFINE_SHIM(XULCommandEvent),
+ DEFINE_SHIM(XULDocument),
+ DEFINE_SHIM(XULElement),
+ DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsISelection, Selection),
+};
+
+#undef DEFINE_SHIM
+#undef DEFINE_SHIM_WITH_CUSTOM_INTERFACE
+
+NS_IMPL_ISUPPORTS(ShimInterfaceInfo, nsISupports, nsIInterfaceInfo)
+
+already_AddRefed<ShimInterfaceInfo>
+ShimInterfaceInfo::MaybeConstruct(const char* aName, JSContext* cx)
+{
+ RefPtr<ShimInterfaceInfo> info;
+ for (uint32_t i = 0; i < ArrayLength(kComponentsInterfaceShimMap); ++i) {
+ if (!strcmp(aName, kComponentsInterfaceShimMap[i].geckoName)) {
+ const ComponentsInterfaceShimEntry& shimEntry =
+ kComponentsInterfaceShimMap[i];
+ info = new ShimInterfaceInfo(shimEntry.iid,
+ shimEntry.geckoName,
+ shimEntry.nativePropHooks);
+ break;
+ }
+ }
+ return info.forget();
+}
+
+ShimInterfaceInfo::ShimInterfaceInfo(const nsIID& aIID,
+ const char* aName,
+ const mozilla::dom::NativePropertyHooks* aNativePropHooks)
+ : mIID(aIID)
+ , mName(aName)
+ , mNativePropHooks(aNativePropHooks)
+{
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetName(char** aName)
+{
+ *aName = ToNewCString(mName);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetInterfaceIID(nsIID** aIID)
+{
+ *aIID = static_cast<nsIID*> (nsMemory::Clone(&mIID, sizeof(mIID)));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::IsScriptable(bool* aRetVal)
+{
+ // This class should pretend that the interface is scriptable because
+ // that's what nsJSIID assumes.
+ *aRetVal = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::IsBuiltinClass(bool* aRetVal)
+{
+ *aRetVal = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::IsMainProcessScriptableOnly(bool* aRetVal)
+{
+ *aRetVal = false;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetParent(nsIInterfaceInfo** aParent)
+{
+ *aParent = nullptr;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetMethodCount(uint16_t* aCount)
+{
+ // Pretend we don't have any methods.
+ *aCount = 0;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetConstantCount(uint16_t* aCount)
+{
+ // We assume that we never have interfaces with more than UINT16_MAX
+ // constants defined on them.
+ uint16_t count = 0;
+
+ // NOTE: The structure of this loop must be kept in sync with the loop
+ // in GetConstant.
+ const mozilla::dom::NativePropertyHooks* propHooks = mNativePropHooks;
+ do {
+ const mozilla::dom::NativeProperties* props[] = {
+ propHooks->mNativeProperties.regular,
+ propHooks->mNativeProperties.chromeOnly
+ };
+ for (size_t i = 0; i < ArrayLength(props); ++i) {
+ auto prop = props[i];
+ if (prop && prop->HasConstants()) {
+ for (auto cs = prop->Constants()->specs; cs->name; ++cs) {
+ // We have found one constant here. We explicitly do not
+ // bother calling isEnabled() here because it's OK to define
+ // potentially extra constants on these shim interfaces.
+ ++count;
+ }
+ }
+ }
+ } while ((propHooks = propHooks->mProtoHooks));
+ *aCount = count;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetMethodInfo(uint16_t aIndex, const nsXPTMethodInfo** aInfo)
+{
+ MOZ_ASSERT(false, "This should never be called");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetMethodInfoForName(const char* aName, uint16_t* aIndex, const nsXPTMethodInfo** aInfo)
+{
+ MOZ_ASSERT(false, "This should never be called");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetConstant(uint16_t aIndex, JS::MutableHandleValue aConstant,
+ char** aName)
+{
+ // We assume that we never have interfaces with more than UINT16_MAX
+ // constants defined on them.
+ uint16_t index = 0;
+
+ // NOTE: The structure of this loop must be kept in sync with the loop
+ // in GetConstantCount.
+ const mozilla::dom::NativePropertyHooks* propHooks = mNativePropHooks;
+ do {
+ const mozilla::dom::NativeProperties* props[] = {
+ propHooks->mNativeProperties.regular,
+ propHooks->mNativeProperties.chromeOnly
+ };
+ for (size_t i = 0; i < ArrayLength(props); ++i) {
+ auto prop = props[i];
+ if (prop && prop->HasConstants()) {
+ for (auto cs = prop->Constants()->specs; cs->name; ++cs) {
+ // We have found one constant here. We explicitly do not
+ // bother calling isEnabled() here because it's OK to define
+ // potentially extra constants on these shim interfaces.
+ if (index == aIndex) {
+ aConstant.set(cs->value);
+ *aName = ToNewCString(nsDependentCString(cs->name));
+ return NS_OK;
+ }
+ ++index;
+ }
+ }
+ }
+ } while ((propHooks = propHooks->mProtoHooks));
+
+ // aIndex was bigger than the number of constants we have.
+ return NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetInfoForParam(uint16_t aIndex, const nsXPTParamInfo* aParam, nsIInterfaceInfo** aRetVal)
+{
+ MOZ_ASSERT(false, "This should never be called");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetIIDForParam(uint16_t aIndex, const nsXPTParamInfo* aParam, nsIID** aRetVal)
+{
+ MOZ_ASSERT(false, "This should never be called");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetTypeForParam(uint16_t aInex, const nsXPTParamInfo* aParam, uint16_t aDimension, nsXPTType* aRetVal)
+{
+ MOZ_ASSERT(false, "This should never be called");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetSizeIsArgNumberForParam(uint16_t aInex, const nsXPTParamInfo* aParam, uint16_t aDimension, uint8_t* aRetVal)
+{
+ MOZ_ASSERT(false, "This should never be called");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetInterfaceIsArgNumberForParam(uint16_t aInex, const nsXPTParamInfo* aParam, uint8_t* aRetVal)
+{
+ MOZ_ASSERT(false, "This should never be called");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::IsIID(const nsIID* aIID, bool* aRetVal)
+{
+ *aRetVal = mIID.Equals(*aIID);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetNameShared(const char** aName)
+{
+ *aName = mName.get();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::GetIIDShared(const nsIID** aIID)
+{
+ *aIID = &mIID;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::IsFunction(bool* aRetVal)
+{
+ *aRetVal = false;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ShimInterfaceInfo::HasAncestor(const nsIID* aIID, bool* aRetVal)
+{
+ *aRetVal = false;
+ return NS_OK;
+}
+
+NS_IMETHODIMP_(nsresult)
+ShimInterfaceInfo::GetIIDForParamNoAlloc(uint16_t aIndex, const nsXPTParamInfo* aInfo, nsIID* aIID)
+{
+ MOZ_ASSERT(false, "This should never be called");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
diff --git a/xpcom/reflect/xptinfo/ShimInterfaceInfo.h b/xpcom/reflect/xptinfo/ShimInterfaceInfo.h
new file mode 100644
index 000000000..868f503a5
--- /dev/null
+++ b/xpcom/reflect/xptinfo/ShimInterfaceInfo.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * 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 ShimInterfaceInfo_h
+#define ShimInterfaceInfo_h
+
+#include "mozilla/Attributes.h"
+#include "nsIInterfaceInfo.h"
+#include "nsString.h"
+#include "nsID.h"
+#include "nsTArray.h"
+#include "xptinfo.h"
+#include "nsAutoPtr.h"
+#include "js/RootingAPI.h"
+
+namespace mozilla {
+namespace dom {
+struct NativePropertyHooks;
+} // namespace dom
+} // namespace mozilla
+
+class ShimInterfaceInfo final : public nsIInterfaceInfo
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINTERFACEINFO
+
+ // Construct a ShimInterfaceInfo object if we have a shim available for aName.
+ // Otherwise, returns nullptr.
+ static already_AddRefed<ShimInterfaceInfo>
+ MaybeConstruct(const char* aName, JSContext* cx);
+
+private:
+ ShimInterfaceInfo(const nsIID& aIID,
+ const char* aName,
+ const mozilla::dom::NativePropertyHooks* aNativePropHooks);
+
+ ~ShimInterfaceInfo() {}
+
+private:
+ nsIID mIID;
+ nsAutoCString mName;
+ const mozilla::dom::NativePropertyHooks* mNativePropHooks;
+};
+
+#endif
diff --git a/xpcom/reflect/xptinfo/TODO b/xpcom/reflect/xptinfo/TODO
new file mode 100644
index 000000000..50215a4fb
--- /dev/null
+++ b/xpcom/reflect/xptinfo/TODO
@@ -0,0 +1,20 @@
+/* jband - 03/24/00 - */
+
+- DOCS
+- improve error handling
+ - should some errors really be warnings?
+ - should autoreg support additional channel to receive warnings so that
+ an installer can decide whether or not to accept the consequences of
+ leaving the newly installed files in place?
+- verification of interfaces (warnings and/or errors)
+ - verify that repeated interfaces are identical in all ways
+ - verify that interface names are always one-to-one with iids
+- check for truncated xpt files and version problems
+ - http://bugzilla.mozilla.org/show_bug.cgi?id=33193
+- TESTS!
+ - e.g. verify the merge stuff really works for various inputs.
+ - we really need a set of .xpt and .zip files and code that does an array
+ of autoreg and interfaceinof use activitities to test various corners
+ of the system.
+- better autoreg logging
+- use only 32 bits for file size?
diff --git a/xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h b/xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h
new file mode 100644
index 000000000..e72153ad2
--- /dev/null
+++ b/xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=4 et sw=4 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 mozilla_XPTInterfaceInfoManager_h_
+#define mozilla_XPTInterfaceInfoManager_h_
+
+#include "nsIInterfaceInfoManager.h"
+#include "nsIMemoryReporter.h"
+
+#include "mozilla/MemoryReporting.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/ReentrantMonitor.h"
+#include "nsDataHashtable.h"
+
+template<typename T> class nsCOMArray;
+class nsIMemoryReporter;
+struct XPTHeader;
+struct XPTInterfaceDirectoryEntry;
+class xptiInterfaceEntry;
+class xptiInterfaceInfo;
+class xptiTypelibGuts;
+
+namespace mozilla {
+
+class XPTInterfaceInfoManager final
+ : public nsIInterfaceInfoManager
+ , public nsIMemoryReporter
+{
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIINTERFACEINFOMANAGER
+ NS_DECL_NSIMEMORYREPORTER
+
+public:
+ // GetSingleton() is infallible
+ static XPTInterfaceInfoManager* GetSingleton();
+ static void FreeInterfaceInfoManager();
+
+ void GetScriptableInterfaces(nsCOMArray<nsIInterfaceInfo>& aInterfaces);
+
+ void RegisterBuffer(char *buf, uint32_t length);
+
+ static Mutex& GetResolveLock()
+ {
+ return GetSingleton()->mResolveLock;
+ }
+
+ xptiInterfaceEntry* GetInterfaceEntryForIID(const nsIID *iid);
+
+ size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
+
+private:
+ XPTInterfaceInfoManager();
+ ~XPTInterfaceInfoManager();
+
+ void InitMemoryReporter();
+
+ void RegisterXPTHeader(XPTHeader* aHeader);
+
+ // idx is the index of this interface in the XPTHeader
+ void VerifyAndAddEntryIfNew(XPTInterfaceDirectoryEntry* iface,
+ uint16_t idx,
+ xptiTypelibGuts* typelib);
+
+private:
+
+ class xptiWorkingSet
+ {
+ public:
+ xptiWorkingSet();
+ ~xptiWorkingSet();
+
+ bool IsValid() const;
+
+ void InvalidateInterfaceInfos();
+ void ClearHashTables();
+
+ // utility methods...
+
+ enum {NOT_FOUND = 0xffffffff};
+
+ // Directory stuff...
+
+ uint32_t GetDirectoryCount();
+ nsresult GetCloneOfDirectoryAt(uint32_t i, nsIFile** dir);
+ nsresult GetDirectoryAt(uint32_t i, nsIFile** dir);
+ bool FindDirectory(nsIFile* dir, uint32_t* index);
+ bool FindDirectoryOfFile(nsIFile* file, uint32_t* index);
+ bool DirectoryAtMatchesPersistentDescriptor(uint32_t i, const char* desc);
+
+ private:
+ uint32_t mFileCount;
+ uint32_t mMaxFileCount;
+
+ public:
+ // XXX make these private with accessors
+ // mTableMonitor must be held across:
+ // * any read from or write to mIIDTable or mNameTable
+ // * any writing to the links between an xptiInterfaceEntry
+ // and its xptiInterfaceInfo (mEntry/mInfo)
+ mozilla::ReentrantMonitor mTableReentrantMonitor;
+ nsDataHashtable<nsIDHashKey, xptiInterfaceEntry*> mIIDTable;
+ nsDataHashtable<nsDepCharHashKey, xptiInterfaceEntry*> mNameTable;
+ };
+
+ // XXX xptiInterfaceInfo want's to poke at the working set itself
+ friend class ::xptiInterfaceInfo;
+ friend class ::xptiInterfaceEntry;
+ friend class ::xptiTypelibGuts;
+
+ xptiWorkingSet mWorkingSet;
+ Mutex mResolveLock;
+};
+
+} // namespace mozilla
+
+#endif
diff --git a/xpcom/reflect/xptinfo/moz.build b/xpcom/reflect/xptinfo/moz.build
new file mode 100644
index 000000000..320949782
--- /dev/null
+++ b/xpcom/reflect/xptinfo/moz.build
@@ -0,0 +1,37 @@
+# -*- 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 += [
+ 'ShimInterfaceInfo.cpp',
+ 'xptiInterfaceInfo.cpp',
+ 'xptiInterfaceInfoManager.cpp',
+ 'xptiTypelibGuts.cpp',
+ 'xptiWorkingSet.cpp',
+]
+
+XPIDL_SOURCES += [
+ 'nsIInterfaceInfo.idl',
+ 'nsIInterfaceInfoManager.idl',
+]
+
+XPIDL_MODULE = 'xpcom_xpti'
+
+EXPORTS += [
+ 'xptinfo.h',
+]
+
+EXPORTS.mozilla += [
+ 'XPTInterfaceInfoManager.h',
+]
+
+LOCAL_INCLUDES += [
+ '/dom/base',
+]
+
+FINAL_LIBRARY = 'xul'
+
+if CONFIG['GNU_CXX']:
+ CXXFLAGS += ['-Wno-error=shadow']
diff --git a/xpcom/reflect/xptinfo/nsIInterfaceInfo.idl b/xpcom/reflect/xptinfo/nsIInterfaceInfo.idl
new file mode 100644
index 000000000..8b902d5ee
--- /dev/null
+++ b/xpcom/reflect/xptinfo/nsIInterfaceInfo.idl
@@ -0,0 +1,101 @@
+/* -*- 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/. */
+
+/* The nsIInterfaceInfo public declaration. */
+
+
+#include "nsISupports.idl"
+
+// forward declaration of non-XPCOM types
+
+[ptr] native nsXPTMethodInfoPtr(nsXPTMethodInfo);
+[ptr] native nsXPTParamInfoPtr(nsXPTParamInfo);
+ native nsXPTType(nsXPTType);
+
+// We bend the rules to do a [shared] nsIID (but this is never scriptable)
+[ptr] native nsIIDPtrShared(nsIID);
+
+%{C++
+class nsXPTMethodInfo;
+class nsXPTParamInfo;
+class nsXPTType;
+%}
+
+[builtinclass, uuid(3820e663-8e22-4789-b470-56bcf7083f2b)]
+interface nsIInterfaceInfo : nsISupports
+{
+ readonly attribute string name;
+ readonly attribute nsIIDPtr InterfaceIID;
+
+ boolean isScriptable();
+ boolean isBuiltinClass();
+
+ readonly attribute nsIInterfaceInfo parent;
+
+ /**
+ * These include counts for parent (and all ancestors).
+ */
+ readonly attribute uint16_t methodCount;
+ readonly attribute uint16_t constantCount;
+
+ /**
+ * These include methods and constants for parent (and all ancestors).
+ *
+ * These do *not* make copies ***explicit bending of XPCOM rules***.
+ */
+
+ void getMethodInfo(in uint16_t index,
+ [shared, retval] out nsXPTMethodInfoPtr info);
+
+ void getMethodInfoForName(in string methodName, out uint16_t index,
+ [shared, retval] out nsXPTMethodInfoPtr info);
+
+ void getConstant(in uint16_t index,
+ out jsval constant,
+ out string name);
+
+
+ /**
+ * Get the interface information or iid associated with a param of some
+ * method in this interface.
+ */
+
+ nsIInterfaceInfo getInfoForParam(in uint16_t methodIndex,
+ [const] in nsXPTParamInfoPtr param);
+
+ nsIIDPtr getIIDForParam(in uint16_t methodIndex,
+ [const] in nsXPTParamInfoPtr param);
+
+
+ /**
+ * These do *not* make copies ***explicit bending of XPCOM rules***.
+ */
+
+ nsXPTType getTypeForParam(in uint16_t methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ in uint16_t dimension);
+
+ uint8_t getSizeIsArgNumberForParam(in uint16_t methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ in uint16_t dimension);
+
+ uint8_t getInterfaceIsArgNumberForParam(in uint16_t methodIndex,
+ [const] in nsXPTParamInfoPtr param);
+
+ boolean isIID(in nsIIDPtr IID);
+
+ void getNameShared([shared,retval] out string name);
+ void getIIDShared([shared,retval] out nsIIDPtrShared iid);
+
+ boolean isFunction();
+
+ boolean hasAncestor(in nsIIDPtr iid);
+
+ [notxpcom] nsresult getIIDForParamNoAlloc(in uint16_t methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ out nsIID iid);
+
+ boolean isMainProcessScriptableOnly();
+};
diff --git a/xpcom/reflect/xptinfo/nsIInterfaceInfoManager.idl b/xpcom/reflect/xptinfo/nsIInterfaceInfoManager.idl
new file mode 100644
index 000000000..bc63aed49
--- /dev/null
+++ b/xpcom/reflect/xptinfo/nsIInterfaceInfoManager.idl
@@ -0,0 +1,28 @@
+/* -*- 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/. */
+
+/* The nsIInterfaceInfoManager public declaration. */
+
+
+#include "nsISupports.idl"
+
+interface nsIInterfaceInfo;
+
+[builtinclass, uuid(1d53d8d9-1d92-428f-b5cc-198b55e897d7)]
+interface nsIInterfaceInfoManager : nsISupports
+{
+ nsIInterfaceInfo getInfoForIID(in nsIIDPtr iid);
+ nsIInterfaceInfo getInfoForName(in string name);
+};
+
+%{C++
+#define NS_INTERFACEINFOMANAGER_SERVICE_CID \
+ { /* 13bef784-f8e0-4f96-85c1-09f9ef4f9a19 */ \
+ 0x13bef784, 0xf8e0, 0x4f96, \
+ {0x85, 0xc1, 0x09, 0xf9, 0xef, 0x4f, 0x9a, 0x19} }
+
+#define NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID \
+ "@mozilla.org/xpti/interfaceinfomanager-service;1"
+%}
diff --git a/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp b/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
new file mode 100644
index 000000000..8ea80fda1
--- /dev/null
+++ b/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
@@ -0,0 +1,742 @@
+/* -*- 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/. */
+
+/* Implementation of xptiInterfaceEntry and xptiInterfaceInfo. */
+
+#include "xptiprivate.h"
+#include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/XPTInterfaceInfoManager.h"
+#include "mozilla/PodOperations.h"
+#include "jsapi.h"
+
+using namespace mozilla;
+
+/* static */ xptiInterfaceEntry*
+xptiInterfaceEntry::Create(const char* name, const nsID& iid,
+ XPTInterfaceDescriptor* aDescriptor,
+ xptiTypelibGuts* aTypelib)
+{
+ int namelen = strlen(name);
+ void* place =
+ XPT_CALLOC8(gXPTIStructArena, sizeof(xptiInterfaceEntry) + namelen);
+ if (!place) {
+ return nullptr;
+ }
+ return new (place) xptiInterfaceEntry(name, namelen, iid, aDescriptor,
+ aTypelib);
+}
+
+xptiInterfaceEntry::xptiInterfaceEntry(const char* name,
+ size_t nameLength,
+ const nsID& iid,
+ XPTInterfaceDescriptor* aDescriptor,
+ xptiTypelibGuts* aTypelib)
+ : mIID(iid)
+ , mDescriptor(aDescriptor)
+ , mTypelib(aTypelib)
+ , mParent(nullptr)
+ , mInfo(nullptr)
+ , mMethodBaseIndex(0)
+ , mConstantBaseIndex(0)
+ , mFlags(0)
+{
+ memcpy(mName, name, nameLength);
+ SetResolvedState(PARTIALLY_RESOLVED);
+}
+
+bool
+xptiInterfaceEntry::Resolve()
+{
+ MutexAutoLock lock(XPTInterfaceInfoManager::GetResolveLock());
+ return ResolveLocked();
+}
+
+bool
+xptiInterfaceEntry::ResolveLocked()
+{
+ int resolvedState = GetResolveState();
+
+ if(resolvedState == FULLY_RESOLVED)
+ return true;
+ if(resolvedState == RESOLVE_FAILED)
+ return false;
+
+ NS_ASSERTION(GetResolveState() == PARTIALLY_RESOLVED, "bad state!");
+
+ // Finish out resolution by finding parent and Resolving it so
+ // we can set the info we get from it.
+
+ uint16_t parent_index = mDescriptor->parent_interface;
+
+ if(parent_index)
+ {
+ xptiInterfaceEntry* parent =
+ mTypelib->GetEntryAt(parent_index - 1);
+
+ if(!parent || !parent->EnsureResolvedLocked())
+ {
+ SetResolvedState(RESOLVE_FAILED);
+ return false;
+ }
+
+ mParent = parent;
+ if (parent->GetHasNotXPCOMFlag()) {
+ SetHasNotXPCOMFlag();
+ } else {
+ for (uint16_t idx = 0; idx < mDescriptor->num_methods; ++idx) {
+ nsXPTMethodInfo* method = reinterpret_cast<nsXPTMethodInfo*>(
+ mDescriptor->method_descriptors + idx);
+ if (method->IsNotXPCOM()) {
+ SetHasNotXPCOMFlag();
+ break;
+ }
+ }
+ }
+
+
+ mMethodBaseIndex =
+ parent->mMethodBaseIndex +
+ parent->mDescriptor->num_methods;
+
+ mConstantBaseIndex =
+ parent->mConstantBaseIndex +
+ parent->mDescriptor->num_constants;
+
+ }
+ LOG_RESOLVE(("+ complete resolve of %s\n", mName));
+
+ SetResolvedState(FULLY_RESOLVED);
+ return true;
+}
+
+/**************************************************/
+// These non-virtual methods handle the delegated nsIInterfaceInfo methods.
+
+nsresult
+xptiInterfaceEntry::GetName(char **name)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *name = (char*) nsMemory::Clone(mName, strlen(mName)+1);
+ return *name ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+nsresult
+xptiInterfaceEntry::GetIID(nsIID **iid)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *iid = (nsIID*) nsMemory::Clone(&mIID, sizeof(nsIID));
+ return *iid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+nsresult
+xptiInterfaceEntry::IsScriptable(bool* result)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *result = GetScriptableFlag();
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::IsFunction(bool* result)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ *result = XPT_ID_IS_FUNCTION(mDescriptor->flags);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetMethodCount(uint16_t* count)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ *count = mMethodBaseIndex +
+ mDescriptor->num_methods;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetConstantCount(uint16_t* count)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(!count)
+ return NS_ERROR_UNEXPECTED;
+
+ *count = mConstantBaseIndex +
+ mDescriptor->num_constants;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetMethodInfo(uint16_t index, const nsXPTMethodInfo** info)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(index < mMethodBaseIndex)
+ return mParent->GetMethodInfo(index, info);
+
+ if(index >= mMethodBaseIndex +
+ mDescriptor->num_methods)
+ {
+ NS_ERROR("bad param");
+ *info = nullptr;
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // else...
+ *info = reinterpret_cast<nsXPTMethodInfo*>
+ (&mDescriptor->method_descriptors[index - mMethodBaseIndex]);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetMethodInfoForName(const char* methodName, uint16_t *index,
+ const nsXPTMethodInfo** result)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ // This is a slow algorithm, but this is not expected to be called much.
+ for(uint16_t i = 0; i < mDescriptor->num_methods; ++i)
+ {
+ const nsXPTMethodInfo* info;
+ info = reinterpret_cast<nsXPTMethodInfo*>
+ (&mDescriptor->
+ method_descriptors[i]);
+ if (PL_strcmp(methodName, info->GetName()) == 0) {
+ *index = i + mMethodBaseIndex;
+ *result = info;
+ return NS_OK;
+ }
+ }
+
+ if(mParent)
+ return mParent->GetMethodInfoForName(methodName, index, result);
+ else
+ {
+ *index = 0;
+ *result = 0;
+ return NS_ERROR_INVALID_ARG;
+ }
+}
+
+nsresult
+xptiInterfaceEntry::GetConstant(uint16_t index, JS::MutableHandleValue constant,
+ char** name)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(index < mConstantBaseIndex)
+ return mParent->GetConstant(index, constant, name);
+
+ if(index >= mConstantBaseIndex +
+ mDescriptor->num_constants)
+ {
+ NS_PRECONDITION(0, "bad param");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const auto& c = mDescriptor->const_descriptors[index - mConstantBaseIndex];
+ AutoJSContext cx;
+ JS::Rooted<JS::Value> v(cx);
+ v.setUndefined();
+
+ switch (c.type.prefix.flags) {
+ case nsXPTType::T_I8:
+ {
+ v.setInt32(c.value.i8);
+ break;
+ }
+ case nsXPTType::T_U8:
+ {
+ v.setInt32(c.value.ui8);
+ break;
+ }
+ case nsXPTType::T_I16:
+ {
+ v.setInt32(c.value.i16);
+ break;
+ }
+ case nsXPTType::T_U16:
+ {
+ v.setInt32(c.value.ui16);
+ break;
+ }
+ case nsXPTType::T_I32:
+ {
+ v = JS_NumberValue(c.value.i32);
+ break;
+ }
+ case nsXPTType::T_U32:
+ {
+ v = JS_NumberValue(c.value.ui32);
+ break;
+ }
+ default:
+ {
+#ifdef DEBUG
+ NS_ERROR("Non-numeric constant found in interface.");
+#endif
+ }
+ }
+
+ constant.set(v);
+ *name = ToNewCString(nsDependentCString(c.name));
+
+ return NS_OK;
+}
+
+// this is a private helper
+
+nsresult
+xptiInterfaceEntry::GetInterfaceIndexForParam(uint16_t methodIndex,
+ const nsXPTParamInfo* param,
+ uint16_t* interfaceIndex)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mMethodBaseIndex)
+ return mParent->GetInterfaceIndexForParam(methodIndex, param,
+ interfaceIndex);
+
+ if(methodIndex >= mMethodBaseIndex +
+ mDescriptor->num_methods)
+ {
+ NS_ERROR("bad param");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td = &param->type;
+
+ while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
+ td = &mDescriptor->additional_types[td->u.array.additional_type];
+ }
+
+ if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_TYPE) {
+ NS_ERROR("not an interface");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *interfaceIndex = (td->u.iface.iface_hi8 << 8) | td->u.iface.iface_lo8;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetEntryForParam(uint16_t methodIndex,
+ const nsXPTParamInfo * param,
+ xptiInterfaceEntry** entry)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mMethodBaseIndex)
+ return mParent->GetEntryForParam(methodIndex, param, entry);
+
+ uint16_t interfaceIndex = 0;
+ nsresult rv = GetInterfaceIndexForParam(methodIndex, param,
+ &interfaceIndex);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ xptiInterfaceEntry* theEntry = mTypelib->GetEntryAt(interfaceIndex - 1);
+
+ // This can happen if a declared interface is not available at runtime.
+ if(!theEntry)
+ {
+ *entry = nullptr;
+ return NS_ERROR_FAILURE;
+ }
+
+ *entry = theEntry;
+ return NS_OK;
+}
+
+already_AddRefed<ShimInterfaceInfo>
+xptiInterfaceEntry::GetShimForParam(uint16_t methodIndex,
+ const nsXPTParamInfo* param)
+{
+ if(methodIndex < mMethodBaseIndex) {
+ return mParent->GetShimForParam(methodIndex, param);
+ }
+
+ uint16_t interfaceIndex = 0;
+ nsresult rv = GetInterfaceIndexForParam(methodIndex, param,
+ &interfaceIndex);
+ if (NS_FAILED(rv)) {
+ return nullptr;
+ }
+
+ const char* shimName = mTypelib->GetEntryNameAt(interfaceIndex - 1);
+ RefPtr<ShimInterfaceInfo> shim =
+ ShimInterfaceInfo::MaybeConstruct(shimName, nullptr);
+ return shim.forget();
+}
+
+nsresult
+xptiInterfaceEntry::GetInfoForParam(uint16_t methodIndex,
+ const nsXPTParamInfo *param,
+ nsIInterfaceInfo** info)
+{
+ xptiInterfaceEntry* entry;
+ nsresult rv = GetEntryForParam(methodIndex, param, &entry);
+ if (NS_FAILED(rv)) {
+ RefPtr<ShimInterfaceInfo> shim = GetShimForParam(methodIndex, param);
+ if (!shim) {
+ return rv;
+ }
+
+ shim.forget(info);
+ return NS_OK;
+ }
+
+ *info = entry->InterfaceInfo().take();
+
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetIIDForParam(uint16_t methodIndex,
+ const nsXPTParamInfo* param, nsIID** iid)
+{
+ xptiInterfaceEntry* entry;
+ nsresult rv = GetEntryForParam(methodIndex, param, &entry);
+ if (NS_FAILED(rv)) {
+ RefPtr<ShimInterfaceInfo> shim = GetShimForParam(methodIndex, param);
+ if (!shim) {
+ return rv;
+ }
+
+ return shim->GetInterfaceIID(iid);
+ }
+ return entry->GetIID(iid);
+}
+
+nsresult
+xptiInterfaceEntry::GetIIDForParamNoAlloc(uint16_t methodIndex,
+ const nsXPTParamInfo * param,
+ nsIID *iid)
+{
+ xptiInterfaceEntry* entry;
+ nsresult rv = GetEntryForParam(methodIndex, param, &entry);
+ if (NS_FAILED(rv)) {
+ RefPtr<ShimInterfaceInfo> shim = GetShimForParam(methodIndex, param);
+ if (!shim) {
+ return rv;
+ }
+
+ const nsIID* shimIID;
+ DebugOnly<nsresult> rv2 = shim->GetIIDShared(&shimIID);
+ MOZ_ASSERT(NS_SUCCEEDED(rv2));
+ *iid = *shimIID;
+ return NS_OK;
+ }
+ *iid = entry->mIID;
+ return NS_OK;
+}
+
+// this is a private helper
+nsresult
+xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param,
+ uint16_t dimension,
+ const XPTTypeDescriptor** type)
+{
+ NS_ASSERTION(IsFullyResolved(), "bad state");
+
+ const XPTTypeDescriptor *td = &param->type;
+ const XPTTypeDescriptor *additional_types =
+ mDescriptor->additional_types;
+
+ for (uint16_t i = 0; i < dimension; i++) {
+ if(XPT_TDP_TAG(td->prefix) != TD_ARRAY) {
+ NS_ERROR("bad dimension");
+ return NS_ERROR_INVALID_ARG;
+ }
+ td = &additional_types[td->u.array.additional_type];
+ }
+
+ *type = td;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetTypeForParam(uint16_t methodIndex,
+ const nsXPTParamInfo* param,
+ uint16_t dimension,
+ nsXPTType* type)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mMethodBaseIndex)
+ return mParent->
+ GetTypeForParam(methodIndex, param, dimension, type);
+
+ if(methodIndex >= mMethodBaseIndex +
+ mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td;
+
+ if(dimension) {
+ nsresult rv = GetTypeInArray(param, dimension, &td);
+ if(NS_FAILED(rv))
+ return rv;
+ }
+ else
+ td = &param->type;
+
+ *type = nsXPTType(td->prefix);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetSizeIsArgNumberForParam(uint16_t methodIndex,
+ const nsXPTParamInfo* param,
+ uint16_t dimension,
+ uint8_t* argnum)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mMethodBaseIndex)
+ return mParent->
+ GetSizeIsArgNumberForParam(methodIndex, param, dimension, argnum);
+
+ if(methodIndex >= mMethodBaseIndex +
+ mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td;
+
+ if(dimension) {
+ nsresult rv = GetTypeInArray(param, dimension, &td);
+ if(NS_FAILED(rv))
+ return rv;
+ }
+ else
+ td = &param->type;
+
+ // verify that this is a type that has size_is
+ switch (XPT_TDP_TAG(td->prefix)) {
+ case TD_ARRAY:
+ *argnum = td->u.array.argnum;
+ break;
+ case TD_PSTRING_SIZE_IS:
+ case TD_PWSTRING_SIZE_IS:
+ *argnum = td->u.pstring_is.argnum;
+ break;
+ default:
+ NS_ERROR("not a size_is");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16_t methodIndex,
+ const nsXPTParamInfo* param,
+ uint8_t* argnum)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mMethodBaseIndex)
+ return mParent->
+ GetInterfaceIsArgNumberForParam(methodIndex, param, argnum);
+
+ if(methodIndex >= mMethodBaseIndex +
+ mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td = &param->type;
+
+ while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
+ td = &mDescriptor->additional_types[td->u.array.additional_type];
+ }
+
+ if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_IS_TYPE) {
+ NS_ERROR("not an iid_is");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *argnum = td->u.interface_is.argnum;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::IsIID(const nsIID * iid, bool *_retval)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *_retval = mIID.Equals(*iid);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetNameShared(const char **name)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *name = mName;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetIIDShared(const nsIID * *iid)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *iid = &mIID;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::HasAncestor(const nsIID * iid, bool *_retval)
+{
+ *_retval = false;
+
+ for(xptiInterfaceEntry* current = this;
+ current;
+ current = current->mParent)
+ {
+ if(current->mIID.Equals(*iid))
+ {
+ *_retval = true;
+ break;
+ }
+ if(!current->EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return NS_OK;
+}
+
+/***************************************************/
+
+already_AddRefed<xptiInterfaceInfo>
+xptiInterfaceEntry::InterfaceInfo()
+{
+#ifdef DEBUG
+ XPTInterfaceInfoManager::GetSingleton()->mWorkingSet.mTableReentrantMonitor.
+ AssertCurrentThreadIn();
+#endif
+
+ if(!mInfo)
+ {
+ mInfo = new xptiInterfaceInfo(this);
+ }
+
+ RefPtr<xptiInterfaceInfo> info = mInfo;
+ return info.forget();
+}
+
+void
+xptiInterfaceEntry::LockedInvalidateInterfaceInfo()
+{
+ if(mInfo)
+ {
+ mInfo->Invalidate();
+ mInfo = nullptr;
+ }
+}
+
+bool
+xptiInterfaceInfo::BuildParent()
+{
+ mozilla::ReentrantMonitorAutoEnter monitor(XPTInterfaceInfoManager::GetSingleton()->
+ mWorkingSet.mTableReentrantMonitor);
+ NS_ASSERTION(mEntry &&
+ mEntry->IsFullyResolved() &&
+ !mParent &&
+ mEntry->Parent(),
+ "bad BuildParent call");
+ mParent = mEntry->Parent()->InterfaceInfo();
+ return true;
+}
+
+/***************************************************************************/
+
+NS_IMPL_QUERY_INTERFACE(xptiInterfaceInfo, nsIInterfaceInfo)
+
+xptiInterfaceInfo::xptiInterfaceInfo(xptiInterfaceEntry* entry)
+ : mEntry(entry)
+{
+}
+
+xptiInterfaceInfo::~xptiInterfaceInfo()
+{
+ NS_ASSERTION(!mEntry, "bad state in dtor");
+}
+
+void
+xptiInterfaceInfo::Invalidate()
+{
+ mParent = nullptr;
+ mEntry = nullptr;
+}
+
+MozExternalRefCountType
+xptiInterfaceInfo::AddRef(void)
+{
+ nsrefcnt cnt = ++mRefCnt;
+ NS_LOG_ADDREF(this, cnt, "xptiInterfaceInfo", sizeof(*this));
+ return cnt;
+}
+
+MozExternalRefCountType
+xptiInterfaceInfo::Release(void)
+{
+ xptiInterfaceEntry* entry = mEntry;
+ nsrefcnt cnt = --mRefCnt;
+ NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo");
+ if(!cnt)
+ {
+ mozilla::ReentrantMonitorAutoEnter monitor(XPTInterfaceInfoManager::
+ GetSingleton()->mWorkingSet.
+ mTableReentrantMonitor);
+
+ // If InterfaceInfo added and *released* a reference before we
+ // acquired the monitor then 'this' might already be dead. In that
+ // case we would not want to try to access any instance data. We
+ // would want to bail immediately. If 'this' is already dead then the
+ // entry will no longer have a pointer to 'this'. So, we can protect
+ // ourselves from danger without more aggressive locking.
+ if(entry && !entry->InterfaceInfoEquals(this))
+ return 0;
+
+ // If InterfaceInfo added a reference before we acquired the monitor
+ // then we want to bail out of here without destorying the object.
+ if(mRefCnt)
+ return 1;
+
+ if(mEntry)
+ {
+ mEntry->LockedInterfaceInfoDeathNotification();
+ mEntry = nullptr;
+ }
+
+ delete this;
+ return 0;
+ }
+ return cnt;
+}
+
+/***************************************************************************/
diff --git a/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp b/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
new file mode 100644
index 000000000..600a99b94
--- /dev/null
+++ b/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
@@ -0,0 +1,242 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 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/. */
+
+/* Implementation of xptiInterfaceInfoManager. */
+
+#include "mozilla/XPTInterfaceInfoManager.h"
+
+#include "mozilla/FileUtils.h"
+#include "mozilla/MemoryReporting.h"
+#include "mozilla/StaticPtr.h"
+
+#include "xptiprivate.h"
+#include "nsDependentString.h"
+#include "nsString.h"
+#include "nsArrayEnumerator.h"
+#include "nsDirectoryService.h"
+#include "nsIMemoryReporter.h"
+
+using namespace mozilla;
+
+NS_IMPL_ISUPPORTS(
+ XPTInterfaceInfoManager,
+ nsIInterfaceInfoManager,
+ nsIMemoryReporter)
+
+static StaticRefPtr<XPTInterfaceInfoManager> gInterfaceInfoManager;
+
+size_t
+XPTInterfaceInfoManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
+{
+ size_t n = aMallocSizeOf(this);
+ ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
+ // The entries themselves are allocated out of an arena accounted
+ // for elsewhere, so don't measure them
+ n += mWorkingSet.mIIDTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
+ n += mWorkingSet.mNameTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
+ return n;
+}
+
+MOZ_DEFINE_MALLOC_SIZE_OF(XPTIMallocSizeOf)
+
+NS_IMETHODIMP
+XPTInterfaceInfoManager::CollectReports(nsIHandleReportCallback* aHandleReport,
+ nsISupports* aData, bool aAnonymize)
+{
+ size_t amount = SizeOfIncludingThis(XPTIMallocSizeOf);
+
+ // Measure gXPTIStructArena here, too. This is a bit grotty because it
+ // doesn't belong to the XPTIInterfaceInfoManager, but there's no
+ // obviously better place to measure it.
+ amount += XPT_SizeOfArenaIncludingThis(gXPTIStructArena, XPTIMallocSizeOf);
+
+ MOZ_COLLECT_REPORT(
+ "explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES, amount,
+ "Memory used by the XPCOM typelib system.");
+
+ return NS_OK;
+}
+
+// static
+XPTInterfaceInfoManager*
+XPTInterfaceInfoManager::GetSingleton()
+{
+ if (!gInterfaceInfoManager) {
+ gInterfaceInfoManager = new XPTInterfaceInfoManager();
+ gInterfaceInfoManager->InitMemoryReporter();
+ }
+ return gInterfaceInfoManager;
+}
+
+void
+XPTInterfaceInfoManager::FreeInterfaceInfoManager()
+{
+ gInterfaceInfoManager = nullptr;
+}
+
+XPTInterfaceInfoManager::XPTInterfaceInfoManager()
+ : mWorkingSet(),
+ mResolveLock("XPTInterfaceInfoManager.mResolveLock")
+{
+}
+
+XPTInterfaceInfoManager::~XPTInterfaceInfoManager()
+{
+ // We only do this on shutdown of the service.
+ mWorkingSet.InvalidateInterfaceInfos();
+
+ UnregisterWeakMemoryReporter(this);
+}
+
+void
+XPTInterfaceInfoManager::InitMemoryReporter()
+{
+ RegisterWeakMemoryReporter(this);
+}
+
+void
+XPTInterfaceInfoManager::RegisterBuffer(char *buf, uint32_t length)
+{
+ XPTState state;
+ XPT_InitXDRState(&state, buf, length);
+
+ XPTCursor curs;
+ NotNull<XPTCursor*> cursor = WrapNotNull(&curs);
+ if (!XPT_MakeCursor(&state, XPT_HEADER, 0, cursor)) {
+ return;
+ }
+
+ XPTHeader *header = nullptr;
+ if (XPT_DoHeader(gXPTIStructArena, cursor, &header)) {
+ RegisterXPTHeader(header);
+ }
+}
+
+void
+XPTInterfaceInfoManager::RegisterXPTHeader(XPTHeader* aHeader)
+{
+ if (aHeader->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION) {
+ NS_ASSERTION(!aHeader->num_interfaces,"bad libxpt");
+ LOG_AUTOREG((" file is version %d.%d Type file of version %d.0 or higher can not be read.\n", (int)header->major_version, (int)header->minor_version, (int)XPT_MAJOR_INCOMPATIBLE_VERSION));
+ }
+
+ xptiTypelibGuts* typelib = xptiTypelibGuts::Create(aHeader);
+
+ ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
+ for(uint16_t k = 0; k < aHeader->num_interfaces; k++)
+ VerifyAndAddEntryIfNew(aHeader->interface_directory + k, k, typelib);
+}
+
+void
+XPTInterfaceInfoManager::VerifyAndAddEntryIfNew(XPTInterfaceDirectoryEntry* iface,
+ uint16_t idx,
+ xptiTypelibGuts* typelib)
+{
+ if (!iface->interface_descriptor)
+ return;
+
+ // 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.
+ if (iface->interface_descriptor->num_methods > 250 &&
+ !(XPT_ID_IS_BUILTINCLASS(iface->interface_descriptor->flags))) {
+ NS_ASSERTION(0, "Too many methods to handle for the stub, cannot load");
+ fprintf(stderr, "ignoring too large interface: %s\n", iface->name);
+ return;
+ }
+
+ mWorkingSet.mTableReentrantMonitor.AssertCurrentThreadIn();
+ xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(iface->iid);
+ if (entry) {
+ // XXX validate this info to find possible inconsistencies
+ LOG_AUTOREG((" ignoring repeated interface: %s\n", iface->name));
+ return;
+ }
+
+ // Build a new xptiInterfaceEntry object and hook it up.
+
+ entry = xptiInterfaceEntry::Create(iface->name,
+ iface->iid,
+ iface->interface_descriptor,
+ typelib);
+ if (!entry)
+ return;
+
+ //XXX We should SetHeader too as part of the validation, no?
+ entry->SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(iface->interface_descriptor->flags));
+ entry->SetBuiltinClassFlag(XPT_ID_IS_BUILTINCLASS(iface->interface_descriptor->flags));
+ entry->SetMainProcessScriptableOnlyFlag(
+ XPT_ID_IS_MAIN_PROCESS_SCRIPTABLE_ONLY(iface->interface_descriptor->flags));
+
+ mWorkingSet.mIIDTable.Put(entry->IID(), entry);
+ mWorkingSet.mNameTable.Put(entry->GetTheName(), entry);
+
+ typelib->SetEntryAt(idx, entry);
+
+ LOG_AUTOREG((" added interface: %s\n", iface->name));
+}
+
+// this is a private helper
+static nsresult
+EntryToInfo(xptiInterfaceEntry* entry, nsIInterfaceInfo **_retval)
+{
+ if (!entry) {
+ *_retval = nullptr;
+ return NS_ERROR_FAILURE;
+ }
+
+ RefPtr<xptiInterfaceInfo> info = entry->InterfaceInfo();
+ info.forget(_retval);
+ return NS_OK;
+}
+
+xptiInterfaceEntry*
+XPTInterfaceInfoManager::GetInterfaceEntryForIID(const nsIID *iid)
+{
+ ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
+ return mWorkingSet.mIIDTable.Get(*iid);
+}
+
+NS_IMETHODIMP
+XPTInterfaceInfoManager::GetInfoForIID(const nsIID * iid, nsIInterfaceInfo **_retval)
+{
+ NS_ASSERTION(iid, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
+ xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(*iid);
+ return EntryToInfo(entry, _retval);
+}
+
+NS_IMETHODIMP
+XPTInterfaceInfoManager::GetInfoForName(const char *name, nsIInterfaceInfo **_retval)
+{
+ NS_ASSERTION(name, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
+ xptiInterfaceEntry* entry = mWorkingSet.mNameTable.Get(name);
+ return EntryToInfo(entry, _retval);
+}
+
+void
+XPTInterfaceInfoManager::GetScriptableInterfaces(nsCOMArray<nsIInterfaceInfo>& aInterfaces)
+{
+ // I didn't want to incur the size overhead of using nsHashtable just to
+ // make building an enumerator easier. So, this code makes a snapshot of
+ // the table using an nsCOMArray and builds an enumerator for that.
+ // We can afford this transient cost.
+
+ ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
+ aInterfaces.SetCapacity(mWorkingSet.mNameTable.Count());
+ for (auto iter = mWorkingSet.mNameTable.Iter(); !iter.Done(); iter.Next()) {
+ xptiInterfaceEntry* entry = iter.UserData();
+ if (entry->GetScriptableFlag()) {
+ nsCOMPtr<nsIInterfaceInfo> ii = entry->InterfaceInfo();
+ aInterfaces.AppendElement(ii);
+ }
+ }
+}
diff --git a/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp b/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp
new file mode 100644
index 000000000..e2965d0b1
--- /dev/null
+++ b/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp
@@ -0,0 +1,74 @@
+/* -*- 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/. */
+
+/* Implementation of xptiTypelibGuts. */
+
+#include "xptiprivate.h"
+#include "mozilla/XPTInterfaceInfoManager.h"
+
+using namespace mozilla;
+
+// Ensure through static analysis that xptiTypelibGuts won't have a vtable.
+template <class T>
+class MOZ_NEEDS_NO_VTABLE_TYPE CheckNoVTable
+{
+};
+CheckNoVTable<xptiTypelibGuts> gChecker;
+
+// static
+xptiTypelibGuts*
+xptiTypelibGuts::Create(XPTHeader* aHeader)
+{
+ NS_ASSERTION(aHeader, "bad param");
+ size_t n = sizeof(xptiTypelibGuts) +
+ sizeof(xptiInterfaceEntry*) * (aHeader->num_interfaces - 1);
+ void* place = XPT_CALLOC8(gXPTIStructArena, n);
+ if (!place)
+ return nullptr;
+ return new(place) xptiTypelibGuts(aHeader);
+}
+
+xptiInterfaceEntry*
+xptiTypelibGuts::GetEntryAt(uint16_t i)
+{
+ static const nsID zeroIID =
+ { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
+
+ NS_ASSERTION(mHeader, "bad state");
+ NS_ASSERTION(i < GetEntryCount(), "bad index");
+
+ xptiInterfaceEntry* r = mEntryArray[i];
+ if (r)
+ return r;
+
+ XPTInterfaceDirectoryEntry* iface = mHeader->interface_directory + i;
+
+ XPTInterfaceInfoManager::xptiWorkingSet& set =
+ XPTInterfaceInfoManager::GetSingleton()->mWorkingSet;
+
+ {
+ ReentrantMonitorAutoEnter monitor(set.mTableReentrantMonitor);
+ if (iface->iid.Equals(zeroIID))
+ r = set.mNameTable.Get(iface->name);
+ else
+ r = set.mIIDTable.Get(iface->iid);
+ }
+
+ if (r)
+ SetEntryAt(i, r);
+
+ return r;
+}
+
+const char*
+xptiTypelibGuts::GetEntryNameAt(uint16_t i)
+{
+ NS_ASSERTION(mHeader, "bad state");
+ NS_ASSERTION(i < GetEntryCount(), "bad index");
+
+ XPTInterfaceDirectoryEntry* iface = mHeader->interface_directory + i;
+
+ return iface->name;
+}
diff --git a/xpcom/reflect/xptinfo/xptiWorkingSet.cpp b/xpcom/reflect/xptinfo/xptiWorkingSet.cpp
new file mode 100644
index 000000000..10f81a4b2
--- /dev/null
+++ b/xpcom/reflect/xptinfo/xptiWorkingSet.cpp
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 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/. */
+
+/* Implementation of xptiWorkingSet. */
+
+#include "mozilla/XPTInterfaceInfoManager.h"
+
+#include "xptiprivate.h"
+#include "nsString.h"
+
+using namespace mozilla;
+
+static const size_t XPTI_ARENA8_BLOCK_SIZE = 16 * 1024;
+static const size_t XPTI_ARENA1_BLOCK_SIZE = 8 * 1024;
+
+static const uint32_t XPTI_HASHTABLE_LENGTH = 1024;
+
+XPTInterfaceInfoManager::xptiWorkingSet::xptiWorkingSet()
+ : mTableReentrantMonitor("xptiWorkingSet::mTableReentrantMonitor")
+ , mIIDTable(XPTI_HASHTABLE_LENGTH)
+ , mNameTable(XPTI_HASHTABLE_LENGTH)
+{
+ MOZ_COUNT_CTOR(xptiWorkingSet);
+
+ gXPTIStructArena = XPT_NewArena(XPTI_ARENA8_BLOCK_SIZE,
+ XPTI_ARENA1_BLOCK_SIZE);
+}
+
+void
+XPTInterfaceInfoManager::xptiWorkingSet::InvalidateInterfaceInfos()
+{
+ ReentrantMonitorAutoEnter monitor(mTableReentrantMonitor);
+ for (auto iter = mNameTable.Iter(); !iter.Done(); iter.Next()) {
+ xptiInterfaceEntry* entry = iter.UserData();
+ entry->LockedInvalidateInterfaceInfo();
+ }
+}
+
+XPTInterfaceInfoManager::xptiWorkingSet::~xptiWorkingSet()
+{
+ MOZ_COUNT_DTOR(xptiWorkingSet);
+
+ // Only destroy the arena if we're doing leak stats. Why waste shutdown
+ // time touching pages if we don't have to?
+#ifdef NS_FREE_PERMANENT_DATA
+ XPT_DestroyArena(gXPTIStructArena);
+#endif
+}
+
+XPTArena* gXPTIStructArena;
diff --git a/xpcom/reflect/xptinfo/xptinfo.h b/xpcom/reflect/xptinfo/xptinfo.h
new file mode 100644
index 000000000..1207a42bb
--- /dev/null
+++ b/xpcom/reflect/xptinfo/xptinfo.h
@@ -0,0 +1,236 @@
+/* -*- 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/. */
+
+/* XPTI_PUBLIC_API and XPTI_GetInterfaceInfoManager declarations. */
+
+#ifndef xptiinfo_h___
+#define xptiinfo_h___
+
+#include "nscore.h"
+#include "xpt_struct.h"
+
+// Flyweight wrapper classes for xpt_struct.h structs.
+// Everything here is dependent upon - and sensitive to changes in -
+// xpcom/typelib/xpt/xpt_struct.h!
+
+class nsXPTType : public XPTTypeDescriptorPrefix
+{
+// NO DATA - this a flyweight wrapper
+public:
+ nsXPTType()
+ {} // random contents
+ MOZ_IMPLICIT nsXPTType(const XPTTypeDescriptorPrefix& prefix)
+ {*(XPTTypeDescriptorPrefix*)this = prefix;}
+
+ MOZ_IMPLICIT nsXPTType(const uint8_t& prefix)
+ {*(uint8_t*)this = prefix;}
+
+ nsXPTType& operator=(uint8_t val)
+ {flags = val; return *this;}
+
+ nsXPTType& operator=(const nsXPTType& other)
+ {flags = other.flags; return *this;}
+
+ operator uint8_t() const
+ {return flags;}
+
+ // 'Arithmetic' here roughly means that the value is self-contained and
+ // doesn't depend on anything else in memory (ie: not a pointer, not an
+ // XPCOM object, not a jsval, etc).
+ //
+ // Supposedly this terminology comes from Harbison/Steele, but it's still
+ // a rather crappy name. We'd change it if it wasn't used all over the
+ // place in xptcall. :-(
+ bool IsArithmetic() const
+ {return flags <= T_WCHAR;}
+
+ // We used to abuse 'pointer' flag bit in typelib format quite extensively.
+ // We've gotten rid of most of the cases, but there's still a fair amount
+ // of refactoring to be done in XPCWrappedJSClass before we can safely stop
+ // asking about this. In the mean time, we've got a temporary version of
+ // IsPointer() that should be equivalent to what's in the typelib.
+ bool deprecated_IsPointer() const
+ {return !IsArithmetic() && TagPart() != T_JSVAL;}
+
+ bool IsInterfacePointer() const
+ { switch (TagPart()) {
+ default:
+ return false;
+ case T_INTERFACE:
+ case T_INTERFACE_IS:
+ return true;
+ }
+ }
+
+ bool IsArray() const
+ {return TagPart() == T_ARRAY;}
+
+ // 'Dependent' means that params of this type are dependent upon other
+ // params. e.g. an T_INTERFACE_IS is dependent upon some other param at
+ // runtime to say what the interface type of this param really is.
+ bool IsDependent() const
+ { switch (TagPart()) {
+ default:
+ return false;
+ case T_INTERFACE_IS:
+ case TD_ARRAY:
+ case T_PSTRING_SIZE_IS:
+ case T_PWSTRING_SIZE_IS:
+ return true;
+ }
+ }
+
+ uint8_t TagPart() const
+ {return (uint8_t) (flags & XPT_TDP_TAGMASK);}
+
+ enum
+ {
+ T_I8 = TD_INT8 ,
+ T_I16 = TD_INT16 ,
+ T_I32 = TD_INT32 ,
+ T_I64 = TD_INT64 ,
+ T_U8 = TD_UINT8 ,
+ T_U16 = TD_UINT16 ,
+ T_U32 = TD_UINT32 ,
+ T_U64 = TD_UINT64 ,
+ T_FLOAT = TD_FLOAT ,
+ T_DOUBLE = TD_DOUBLE ,
+ T_BOOL = TD_BOOL ,
+ T_CHAR = TD_CHAR ,
+ T_WCHAR = TD_WCHAR ,
+ T_VOID = TD_VOID ,
+ T_IID = TD_PNSIID ,
+ T_DOMSTRING = TD_DOMSTRING ,
+ T_CHAR_STR = TD_PSTRING ,
+ T_WCHAR_STR = TD_PWSTRING ,
+ T_INTERFACE = TD_INTERFACE_TYPE ,
+ T_INTERFACE_IS = TD_INTERFACE_IS_TYPE,
+ T_ARRAY = TD_ARRAY ,
+ T_PSTRING_SIZE_IS = TD_PSTRING_SIZE_IS ,
+ T_PWSTRING_SIZE_IS = TD_PWSTRING_SIZE_IS ,
+ T_UTF8STRING = TD_UTF8STRING ,
+ T_CSTRING = TD_CSTRING ,
+ T_ASTRING = TD_ASTRING ,
+ T_JSVAL = TD_JSVAL
+ };
+// NO DATA - this a flyweight wrapper
+};
+
+class nsXPTParamInfo : public XPTParamDescriptor
+{
+// NO DATA - this a flyweight wrapper
+public:
+ MOZ_IMPLICIT nsXPTParamInfo(const XPTParamDescriptor& desc)
+ {*(XPTParamDescriptor*)this = desc;}
+
+
+ bool IsIn() const {return 0 != (XPT_PD_IS_IN(flags));}
+ bool IsOut() const {return 0 != (XPT_PD_IS_OUT(flags));}
+ bool IsRetval() const {return 0 != (XPT_PD_IS_RETVAL(flags));}
+ bool IsShared() const {return 0 != (XPT_PD_IS_SHARED(flags));}
+
+ // Dipper types are one of the more inscrutable aspects of xpidl. In a
+ // nutshell, dippers are empty container objects, created and passed by
+ // the caller, and filled by the callee. The callee receives a fully-
+ // formed object, and thus does not have to construct anything. But
+ // the object is functionally empty, and the callee is responsible for
+ // putting something useful inside of it.
+ //
+ // XPIDL decides which types to make dippers. The list of these types
+ // is given in the isDipperType() function in typelib.py, and is currently
+ // limited to 4 string types.
+ //
+ // When a dipper type is declared as an 'out' parameter, xpidl internally
+ // converts it to an 'in', and sets the XPT_PD_DIPPER flag on it. For this
+ // reason, dipper types are sometimes referred to as 'out parameters
+ // masquerading as in'. The burden of maintaining this illusion falls mostly
+ // on XPConnect, which creates the empty containers, and harvest the results
+ // after the call.
+ bool IsDipper() const {return 0 != (XPT_PD_IS_DIPPER(flags));}
+ bool IsOptional() const {return 0 != (XPT_PD_IS_OPTIONAL(flags));}
+ const nsXPTType GetType() const {return type.prefix;}
+
+ bool IsStringClass() const {
+ switch (GetType().TagPart()) {
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // Whether this parameter is passed indirectly on the stack. This mainly
+ // applies to out/inout params, but we use it unconditionally for certain
+ // types.
+ bool IsIndirect() const {return IsOut() ||
+ GetType().TagPart() == nsXPTType::T_JSVAL;}
+
+ // NOTE: other activities on types are done via methods on nsIInterfaceInfo
+
+private:
+ nsXPTParamInfo(); // no implementation
+// NO DATA - this a flyweight wrapper
+};
+
+class nsXPTMethodInfo : public XPTMethodDescriptor
+{
+// NO DATA - this a flyweight wrapper
+public:
+ MOZ_IMPLICIT nsXPTMethodInfo(const XPTMethodDescriptor& desc)
+ {*(XPTMethodDescriptor*)this = desc;}
+
+ bool IsGetter() const {return 0 != (XPT_MD_IS_GETTER(flags) );}
+ bool IsSetter() const {return 0 != (XPT_MD_IS_SETTER(flags) );}
+ bool IsNotXPCOM() const {return 0 != (XPT_MD_IS_NOTXPCOM(flags));}
+ bool IsHidden() const {return 0 != (XPT_MD_IS_HIDDEN(flags) );}
+ bool WantsOptArgc() const {return 0 != (XPT_MD_WANTS_OPT_ARGC(flags));}
+ bool WantsContext() const {return 0 != (XPT_MD_WANTS_CONTEXT(flags));}
+ const char* GetName() const {return name;}
+ uint8_t GetParamCount() const {return num_args;}
+ /* idx was index before I got _sick_ of the warnings on Unix, sorry jband */
+ const nsXPTParamInfo GetParam(uint8_t idx) const
+ {
+ NS_PRECONDITION(idx < GetParamCount(),"bad arg");
+ return params[idx];
+ }
+ const nsXPTParamInfo GetResult() const
+ {return result;}
+private:
+ nsXPTMethodInfo(); // no implementation
+// NO DATA - this a flyweight wrapper
+};
+
+
+// forward declaration
+struct nsXPTCMiniVariant;
+
+class nsXPTConstant : public XPTConstDescriptor
+{
+// NO DATA - this a flyweight wrapper
+public:
+ MOZ_IMPLICIT nsXPTConstant(const XPTConstDescriptor& desc)
+ {*(XPTConstDescriptor*)this = desc;}
+
+ const char* GetName() const
+ {return name;}
+
+ const nsXPTType GetType() const
+ {return type.prefix;}
+
+ // XXX this is ugly. But sometimes you gotta do what you gotta do.
+ // A reinterpret_cast won't do the trick here. And this plain C cast
+ // works correctly and is safe enough.
+ // See http://bugzilla.mozilla.org/show_bug.cgi?id=49641
+ const nsXPTCMiniVariant* GetValue() const
+ {return (nsXPTCMiniVariant*) &value;}
+private:
+ nsXPTConstant(); // no implementation
+// NO DATA - this a flyweight wrapper
+};
+
+#endif /* xptiinfo_h___ */
diff --git a/xpcom/reflect/xptinfo/xptiprivate.h b/xpcom/reflect/xptinfo/xptiprivate.h
new file mode 100644
index 000000000..c32ef9c77
--- /dev/null
+++ b/xpcom/reflect/xptinfo/xptiprivate.h
@@ -0,0 +1,394 @@
+/* -*- 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/. */
+
+/* Library-private header for Interface Info system. */
+
+#ifndef xptiprivate_h___
+#define xptiprivate_h___
+
+#include "nscore.h"
+#include <new>
+#include "nsISupports.h"
+
+// this after nsISupports, to pick up IID
+// so that xpt stuff doesn't try to define it itself...
+#include "xpt_struct.h"
+#include "xpt_xdr.h"
+
+#include "nsIInterfaceInfo.h"
+#include "nsIInterfaceInfoManager.h"
+#include "xptinfo.h"
+#include "ShimInterfaceInfo.h"
+
+#include "nsIServiceManager.h"
+#include "nsIFile.h"
+#include "nsIDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsIWeakReference.h"
+
+#include "mozilla/ReentrantMonitor.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/Attributes.h"
+
+#include "js/TypeDecls.h"
+
+#include "nsCRT.h"
+#include "nsMemory.h"
+
+#include "nsCOMArray.h"
+#include "nsQuickSort.h"
+
+#include "nsXPIDLString.h"
+
+#include "nsIInputStream.h"
+
+#include "nsHashKeys.h"
+#include "nsDataHashtable.h"
+#include "plstr.h"
+#include "prprf.h"
+#include "prio.h"
+#include "prtime.h"
+#include "prenv.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/***************************************************************************/
+
+#if 0 && defined(DEBUG_jband)
+#define LOG_RESOLVE(x) printf x
+#define LOG_LOAD(x) printf x
+#define LOG_AUTOREG(x) do{printf x; xptiInterfaceInfoManager::WriteToLog x;}while(0)
+#else
+#define LOG_RESOLVE(x) ((void)0)
+#define LOG_LOAD(x) ((void)0)
+#define LOG_AUTOREG(x) ((void)0)
+#endif
+
+#if 1 && defined(DEBUG_jband)
+#define SHOW_INFO_COUNT_STATS
+#endif
+
+/***************************************************************************/
+
+class xptiInterfaceInfo;
+class xptiInterfaceEntry;
+class xptiTypelibGuts;
+
+extern XPTArena* gXPTIStructArena;
+
+/***************************************************************************/
+
+/***************************************************************************/
+
+// No virtuals.
+// These are always constructed in the struct arena using placement new.
+// dtor need not be called.
+
+class xptiTypelibGuts
+{
+public:
+ static xptiTypelibGuts* Create(XPTHeader* aHeader);
+
+ XPTHeader* GetHeader() {return mHeader;}
+ uint16_t GetEntryCount() const {return mHeader->num_interfaces;}
+
+ void SetEntryAt(uint16_t i, xptiInterfaceEntry* ptr)
+ {
+ NS_ASSERTION(mHeader,"bad state!");
+ NS_ASSERTION(i < GetEntryCount(),"bad param!");
+ mEntryArray[i] = ptr;
+ }
+
+ xptiInterfaceEntry* GetEntryAt(uint16_t i);
+ const char* GetEntryNameAt(uint16_t i);
+
+private:
+ explicit xptiTypelibGuts(XPTHeader* aHeader)
+ : mHeader(aHeader)
+ { }
+ ~xptiTypelibGuts();
+
+private:
+ XPTHeader* mHeader; // hold pointer into arena
+ xptiInterfaceEntry* mEntryArray[1]; // Always last. Sized to fit.
+};
+
+/***************************************************************************/
+
+/***************************************************************************/
+
+// This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value
+// and a set of bitflags in one 8bit value. See below.
+
+class xptiInfoFlags
+{
+ enum {STATE_MASK = 3};
+public:
+ explicit xptiInfoFlags(uint8_t n) : mData(n) {}
+ xptiInfoFlags(const xptiInfoFlags& r) : mData(r.mData) {}
+
+ static uint8_t GetStateMask()
+ {return uint8_t(STATE_MASK);}
+
+ void Clear()
+ {mData = 0;}
+
+ uint8_t GetData() const
+ {return mData;}
+
+ uint8_t GetState() const
+ {return mData & GetStateMask();}
+
+ void SetState(uint8_t state)
+ {mData &= ~GetStateMask(); mData |= state;}
+
+ void SetFlagBit(uint8_t flag, bool on)
+ {if(on)
+ mData |= ~GetStateMask() & flag;
+ else
+ mData &= GetStateMask() | ~flag;}
+
+ bool GetFlagBit(uint8_t flag) const
+ {return (mData & flag) ? true : false;}
+
+private:
+ uint8_t mData;
+};
+
+/****************************************************/
+
+// No virtual methods.
+// We always create in the struct arena and construct using "placement new".
+// No members need dtor calls.
+
+class xptiInterfaceEntry
+{
+public:
+ static xptiInterfaceEntry* Create(const char* name,
+ const nsID& iid,
+ XPTInterfaceDescriptor* aDescriptor,
+ xptiTypelibGuts* aTypelib);
+
+ enum {
+ PARTIALLY_RESOLVED = 1,
+ FULLY_RESOLVED = 2,
+ RESOLVE_FAILED = 3
+ };
+
+ // Additional bit flags...
+ enum {SCRIPTABLE = 4, BUILTINCLASS = 8, HASNOTXPCOM = 16,
+ MAIN_PROCESS_SCRIPTABLE_ONLY = 32};
+
+ uint8_t GetResolveState() const {return mFlags.GetState();}
+
+ bool IsFullyResolved() const
+ {return GetResolveState() == (uint8_t) FULLY_RESOLVED;}
+
+ void SetScriptableFlag(bool on)
+ {mFlags.SetFlagBit(uint8_t(SCRIPTABLE),on);}
+ bool GetScriptableFlag() const
+ {return mFlags.GetFlagBit(uint8_t(SCRIPTABLE));}
+ void SetBuiltinClassFlag(bool on)
+ {mFlags.SetFlagBit(uint8_t(BUILTINCLASS),on);}
+ bool GetBuiltinClassFlag() const
+ {return mFlags.GetFlagBit(uint8_t(BUILTINCLASS));}
+ void SetMainProcessScriptableOnlyFlag(bool on)
+ {mFlags.SetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY),on);}
+ bool GetMainProcessScriptableOnlyFlag() const
+ {return mFlags.GetFlagBit(uint8_t(MAIN_PROCESS_SCRIPTABLE_ONLY));}
+
+
+ // AddRef/Release are special and are not considered for the NOTXPCOM flag.
+ void SetHasNotXPCOMFlag()
+ {
+ mFlags.SetFlagBit(HASNOTXPCOM, true);
+ }
+ bool GetHasNotXPCOMFlag() const
+ {
+ return mFlags.GetFlagBit(HASNOTXPCOM);
+ }
+
+ const nsID* GetTheIID() const {return &mIID;}
+ const char* GetTheName() const {return mName;}
+
+ bool EnsureResolved()
+ {return IsFullyResolved() ? true : Resolve();}
+
+ already_AddRefed<xptiInterfaceInfo> InterfaceInfo();
+ bool InterfaceInfoEquals(const xptiInterfaceInfo* info) const
+ {return info == mInfo;}
+
+ void LockedInvalidateInterfaceInfo();
+ void LockedInterfaceInfoDeathNotification() {mInfo = nullptr;}
+
+ xptiInterfaceEntry* Parent() const {
+ NS_ASSERTION(IsFullyResolved(), "Parent() called while not resolved?");
+ return mParent;
+ }
+
+ const nsID& IID() const { return mIID; }
+
+ //////////////////////
+ // These non-virtual methods handle the delegated nsIInterfaceInfo methods.
+
+ nsresult GetName(char * *aName);
+ nsresult GetIID(nsIID * *aIID);
+ nsresult IsScriptable(bool *_retval);
+ nsresult IsBuiltinClass(bool *_retval) {
+ *_retval = GetBuiltinClassFlag();
+ return NS_OK;
+ }
+ nsresult IsMainProcessScriptableOnly(bool *_retval) {
+ *_retval = GetMainProcessScriptableOnlyFlag();
+ return NS_OK;
+ }
+ // Except this one.
+ //nsresult GetParent(nsIInterfaceInfo * *aParent);
+ nsresult GetMethodCount(uint16_t *aMethodCount);
+ nsresult GetConstantCount(uint16_t *aConstantCount);
+ nsresult GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info);
+ nsresult GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info);
+ nsresult GetConstant(uint16_t index, JS::MutableHandleValue, char** constant);
+ nsresult GetInfoForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval);
+ nsresult GetIIDForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID * *_retval);
+ nsresult GetTypeForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, nsXPTType *_retval);
+ nsresult GetSizeIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, uint8_t *_retval);
+ nsresult GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval);
+ nsresult IsIID(const nsIID * IID, bool *_retval);
+ nsresult GetNameShared(const char **name);
+ nsresult GetIIDShared(const nsIID * *iid);
+ nsresult IsFunction(bool *_retval);
+ nsresult HasAncestor(const nsIID * iid, bool *_retval);
+ nsresult GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid);
+
+private:
+ xptiInterfaceEntry(const char* name,
+ size_t nameLength,
+ const nsID& iid,
+ XPTInterfaceDescriptor* aDescriptor,
+ xptiTypelibGuts* aTypelib);
+ ~xptiInterfaceEntry();
+
+ void SetResolvedState(int state)
+ {mFlags.SetState(uint8_t(state));}
+
+ bool Resolve();
+
+ // We only call these "*Locked" variants after locking. This is done to
+ // allow reentrace as files are loaded and various interfaces resolved
+ // without having to worry about the locked state.
+
+ bool EnsureResolvedLocked()
+ {return IsFullyResolved() ? true : ResolveLocked();}
+ bool ResolveLocked();
+
+ // private helpers
+
+ nsresult GetEntryForParam(uint16_t methodIndex,
+ const nsXPTParamInfo * param,
+ xptiInterfaceEntry** entry);
+
+ nsresult GetTypeInArray(const nsXPTParamInfo* param,
+ uint16_t dimension,
+ const XPTTypeDescriptor** type);
+
+ nsresult GetInterfaceIndexForParam(uint16_t methodIndex,
+ const nsXPTParamInfo* param,
+ uint16_t* interfaceIndex);
+
+ already_AddRefed<ShimInterfaceInfo>
+ GetShimForParam(uint16_t methodIndex, const nsXPTParamInfo* param);
+
+private:
+ nsID mIID;
+ XPTInterfaceDescriptor* mDescriptor;
+
+ xptiTypelibGuts* mTypelib;
+
+ xptiInterfaceEntry* mParent; // Valid only when fully resolved
+
+ xptiInterfaceInfo* MOZ_UNSAFE_REF("The safety of this pointer is ensured "
+ "by the semantics of xptiWorkingSet.")
+ mInfo; // May come and go.
+
+ uint16_t mMethodBaseIndex;
+ uint16_t mConstantBaseIndex;
+
+ xptiInfoFlags mFlags;
+
+ char mName[1]; // Always last. Sized to fit.
+};
+
+class xptiInterfaceInfo final : public nsIInterfaceInfo
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+
+ // Use delegation to implement (most!) of nsIInterfaceInfo.
+ NS_IMETHOD GetName(char * *aName) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); }
+ NS_IMETHOD GetInterfaceIID(nsIID * *aIID) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); }
+ NS_IMETHOD IsScriptable(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); }
+ NS_IMETHOD IsBuiltinClass(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsBuiltinClass(_retval); }
+ NS_IMETHOD IsMainProcessScriptableOnly(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsMainProcessScriptableOnly(_retval); }
+ // Except this one.
+ NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent) override
+ {
+ if(!EnsureResolved() || !EnsureParent())
+ return NS_ERROR_UNEXPECTED;
+ NS_IF_ADDREF(*aParent = mParent);
+ return NS_OK;
+ }
+ NS_IMETHOD GetMethodCount(uint16_t *aMethodCount) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodCount(aMethodCount); }
+ NS_IMETHOD GetConstantCount(uint16_t *aConstantCount) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstantCount(aConstantCount); }
+ NS_IMETHOD GetMethodInfo(uint16_t index, const nsXPTMethodInfo * *info) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfo(index, info); }
+ NS_IMETHOD GetMethodInfoForName(const char *methodName, uint16_t *index, const nsXPTMethodInfo * *info) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfoForName(methodName, index, info); }
+ NS_IMETHOD GetConstant(uint16_t index, JS::MutableHandleValue constant, char** name) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstant(index, constant, name); }
+ NS_IMETHOD GetInfoForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInfoForParam(methodIndex, param, _retval); }
+ NS_IMETHOD GetIIDForParam(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParam(methodIndex, param, _retval); }
+ NS_IMETHOD GetTypeForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, nsXPTType *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetTypeForParam(methodIndex, param, dimension, _retval); }
+ NS_IMETHOD GetSizeIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint16_t dimension, uint8_t *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetSizeIsArgNumberForParam(methodIndex, param, dimension, _retval); }
+ NS_IMETHOD GetInterfaceIsArgNumberForParam(uint16_t methodIndex, const nsXPTParamInfo * param, uint8_t *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInterfaceIsArgNumberForParam(methodIndex, param, _retval); }
+ NS_IMETHOD IsIID(const nsIID * IID, bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsIID(IID, _retval); }
+ NS_IMETHOD GetNameShared(const char **name) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetNameShared(name); }
+ NS_IMETHOD GetIIDShared(const nsIID * *iid) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDShared(iid); }
+ NS_IMETHOD IsFunction(bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsFunction(_retval); }
+ NS_IMETHOD HasAncestor(const nsIID * iid, bool *_retval) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->HasAncestor(iid, _retval); }
+ NS_IMETHOD GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid) override { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParamNoAlloc(methodIndex, param, iid); }
+
+public:
+ explicit xptiInterfaceInfo(xptiInterfaceEntry* entry);
+
+ void Invalidate();
+
+private:
+
+ ~xptiInterfaceInfo();
+
+ // Note that mParent might still end up as nullptr if we don't have one.
+ bool EnsureParent()
+ {
+ NS_ASSERTION(mEntry && mEntry->IsFullyResolved(), "bad EnsureParent call");
+ return mParent || !mEntry->Parent() || BuildParent();
+ }
+
+ bool EnsureResolved()
+ {
+ return mEntry && mEntry->EnsureResolved();
+ }
+
+ bool BuildParent();
+
+ xptiInterfaceInfo(); // not implemented
+
+private:
+ xptiInterfaceEntry* mEntry;
+ RefPtr<xptiInterfaceInfo> mParent;
+};
+
+/***************************************************************************/
+
+#endif /* xptiprivate_h___ */