diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /xpcom/reflect | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xpcom/reflect')
140 files changed, 18547 insertions, 0 deletions
diff --git a/xpcom/reflect/moz.build b/xpcom/reflect/moz.build new file mode 100644 index 0000000000..fca3fa4499 --- /dev/null +++ b/xpcom/reflect/moz.build @@ -0,0 +1,7 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += ["xptinfo", "xptcall"] diff --git a/xpcom/reflect/xptcall/README b/xpcom/reflect/xptcall/README new file mode 100644 index 0000000000..0c401fe88d --- /dev/null +++ b/xpcom/reflect/xptcall/README @@ -0,0 +1,6 @@ +see: + +http://www.mozilla.org/scriptable/xptcall-faq.html +and +http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html + diff --git a/xpcom/reflect/xptcall/genstubs.pl b/xpcom/reflect/xptcall/genstubs.pl new file mode 100644 index 0000000000..29797ccc58 --- /dev/null +++ b/xpcom/reflect/xptcall/genstubs.pl @@ -0,0 +1,87 @@ +#!/usr/local/bin/perl +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +# This is used to generate stub entry points. We generate a file to +# be included in the declaraion and a file to be used for expanding macros +# to represent the implementation of the stubs. + +# +# if "$entry_count" is ever changed and the .inc files regenerated then +# the following issues need to be addressed: +# +# 1) The current Linux ARM code has a limitation of only having 256-3 stubs, +# as a result of the limitations of immediate values in ARM assembly. +# +# This number is verified by the IDL parser in xpcom/idl-parser/xpidl.py, as +# well as in xpcom/reflect/xptinfo/xptinfo.cpp, to prevent generating interfaces +# or loading xpt files that would cause the stubs to run off the entries. +# If you change this number, please update that location. + +# 3 entries are already 'used' by the 3 methods of nsISupports. +# 3+247+5=255 This should get us in under the Linux ARM limitation +$entry_count = 247; +$sentinel_count = 5; + +$decl_name = "xptcstubsdecl.inc"; +$def_name = "xptcstubsdef.inc"; + +## +## Write the declarations include file +## + +die "Can't open $decl_name" if !open(OUTFILE, ">$decl_name"); + +print OUTFILE "/* generated file - DO NOT EDIT */\n\n"; +print OUTFILE "/* includes ",$entry_count," stub entries, and ", + $sentinel_count," sentinel entries */\n\n"; +print OUTFILE "/*\n"; +print OUTFILE "* declarations of normal stubs...\n"; +print OUTFILE "* 0 is QueryInterface\n"; +print OUTFILE "* 1 is AddRef\n"; +print OUTFILE "* 2 is Release\n"; +print OUTFILE "*/\n"; +print OUTFILE "#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__))\n"; +for($i = 0; $i < $entry_count; $i++) { + print OUTFILE "NS_IMETHOD Stub",$i+3,"();\n"; +} +print OUTFILE "#else\n"; +for($i = 0; $i < $entry_count; $i++) { + print OUTFILE "NS_IMETHOD Stub",$i+3,"(uint64_t,uint64_t,\n"; + print OUTFILE " uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);\n"; + +} +print OUTFILE "#endif\n"; + +print OUTFILE "\n/* declarations of sentinel stubs */\n"; + +for($i = 0; $i < $sentinel_count; $i++) { + print OUTFILE "NS_IMETHOD Sentinel",$i,"();\n"; +} +close(OUTFILE); + + +## +## Write the definitions include file. This assumes a macro will be used to +## expand the entries written... +## + +die "Can't open $def_name" if !open(OUTFILE, ">$def_name"); + +## Disabled for bug 275004 - followup to fix is Bug 419604 +my $warn_inc_is_generated = 0; +if ($warn_inc_is_generated) { +print OUTFILE "/* generated file - DO NOT EDIT */\n\n"; +print OUTFILE "/* includes ",$entry_count," stub entries, and ", + $sentinel_count," sentinel entries */\n\n"; +} + +for($i = 0; $i < $entry_count; $i++) { + print OUTFILE "STUB_ENTRY(",$i+3,")\n"; +} + +for($i = 0; $i < $sentinel_count; $i++) { + print OUTFILE "SENTINEL_ENTRY(",$i,")\n"; +} diff --git a/xpcom/reflect/xptcall/md/moz.build b/xpcom/reflect/xptcall/md/moz.build new file mode 100644 index 0000000000..fcf4dde72f --- /dev/null +++ b/xpcom/reflect/xptcall/md/moz.build @@ -0,0 +1,12 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +arch = CONFIG["OS_ARCH"] + +if arch == "WINNT": + DIRS += ["win32"] +else: + DIRS += ["unix"] diff --git a/xpcom/reflect/xptcall/md/test/README b/xpcom/reflect/xptcall/md/test/README new file mode 100644 index 0000000000..04850b2e01 --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/README @@ -0,0 +1,6 @@ +These are just simple test programs in which stripped down versions of the +XPConnect invoke and stubs code can be built and tested as the code is brought +up on various platforms. These probrams do not test the param sizing and copying +functionality of the routines. However, they do supply a place where the lowest +level assembly language code can be developed and debugged in the simplest of +contexts before it is moved into the real routines.
\ No newline at end of file diff --git a/xpcom/reflect/xptcall/md/test/clean.bat b/xpcom/reflect/xptcall/md/test/clean.bat new file mode 100755 index 0000000000..f320e222c9 --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/clean.bat @@ -0,0 +1,5 @@ +@echo off +echo deleting intermediate files +if exist *.obj del *.obj > NUL +if exist *.ilk del *.ilk > NUL +if exist *.pdb del *.pdb > NUL
\ No newline at end of file diff --git a/xpcom/reflect/xptcall/md/test/invoke_test.cpp b/xpcom/reflect/xptcall/md/test/invoke_test.cpp new file mode 100644 index 0000000000..f23a9ccf15 --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/invoke_test.cpp @@ -0,0 +1,187 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <stdio.h> + +typedef unsigned nsresult; +typedef unsigned uint32_t; +typedef unsigned nsXPCVariant; + +#if defined(WIN32) +# define NS_IMETHOD virtual nsresult __stdcall +# define NS_IMETHODIMP nsresult __stdcall +#else +# define NS_IMETHOD virtual nsresult +# define NS_IMETHODIMP nsresult +#endif + +class base { + public: + NS_IMETHOD ignored() = 0; +}; + +class foo : public base { + public: + NS_IMETHOD callme1(int i, int j) = 0; + NS_IMETHOD callme2(int i, int j) = 0; + NS_IMETHOD callme3(int i, int j) = 0; +}; + +class bar : public foo { + public: + NS_IMETHOD ignored() override; + NS_IMETHOD callme1(int i, int j) override; + NS_IMETHOD callme2(int i, int j) override; + NS_IMETHOD callme3(int i, int j) override; +}; + +/* +class baz : public base { +public: + NS_IMETHOD ignored() override; + NS_IMETHOD callme1() override; + NS_IMETHOD callme2() override; + NS_IMETHOD callme3() override; + void setfoo(foo* f) {other = f;} + + foo* other; +}; +NS_IMETHODIMP baz::ignored(){return 0;} +*/ + +NS_IMETHODIMP bar::ignored() { return 0; } + +NS_IMETHODIMP bar::callme1(int i, int j) { + printf("called bar::callme1 with: %d %d\n", i, j); + return 5; +} + +NS_IMETHODIMP bar::callme2(int i, int j) { + printf("called bar::callme2 with: %d %d\n", i, j); + return 5; +} + +NS_IMETHODIMP bar::callme3(int i, int j) { + printf("called bar::callme3 with: %d %d\n", i, j); + return 5; +} + +void docall(foo* f, int i, int j) { f->callme1(i, j); } + +/***************************************************************************/ +#if defined(WIN32) + +static uint32_t __stdcall invoke_count_words(uint32_t paramCount, + nsXPCVariant* s) { + return paramCount; +} + +static void __stdcall invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, + nsXPCVariant* s) { + for (uint32_t i = 0; i < paramCount; i++, d++, s++) { + *((uint32_t*)d) = *((uint32_t*)s); + } +} + +static nsresult __stdcall DoInvoke(void* that, uint32_t index, + uint32_t paramCount, nsXPCVariant* params) { + __asm { + push params + push paramCount + call invoke_count_words // stdcall, result in eax + shl eax,2 // *= 4 + sub esp,eax // make space for params + mov edx,esp + push params + push paramCount + push edx + call invoke_copy_to_stack // stdcall + mov ecx,that // instance in ecx + push ecx // push this + mov edx,[ecx] // vtable in edx + mov eax,index + shl eax,2 // *= 4 + add edx,eax + call [edx] // stdcall, i.e. callee cleans up stack. + } +} + +#else +/***************************************************************************/ +// just Linux_x86 now. Add other later... + +static uint32_t invoke_count_words(uint32_t paramCount, nsXPCVariant* s) { + return paramCount; +} + +static void invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, + nsXPCVariant* s) { + for (uint32_t i = 0; i < paramCount; i++, d++, s++) { + *((uint32_t*)d) = *((uint32_t*)s); + } +} + +static nsresult DoInvoke(void* that, uint32_t index, uint32_t paramCount, + nsXPCVariant* params) { + uint32_t result; + void* fn_count = invoke_count_words; + void* fn_copy = invoke_copy_to_stack; + + __asm__ __volatile__( + "pushl %4\n\t" + "pushl %3\n\t" + "movl %5, %%eax\n\t" + "call *%%eax\n\t" /* count words */ + "addl $0x8, %%esp\n\t" + "shl $2, %%eax\n\t" /* *= 4 */ + "subl %%eax, %%esp\n\t" /* make room for params */ + "movl %%esp, %%edx\n\t" + "pushl %4\n\t" + "pushl %3\n\t" + "pushl %%edx\n\t" + "movl %6, %%eax\n\t" + "call *%%eax\n\t" /* copy params */ + "addl $0xc, %%esp\n\t" + "movl %1, %%ecx\n\t" + "pushl %%ecx\n\t" + "movl (%%ecx), %%edx\n\t" + "movl %2, %%eax\n\t" /* function index */ + "shl $2, %%eax\n\t" /* *= 4 */ + "addl $8, %%eax\n\t" /* += 8 */ + "addl %%eax, %%edx\n\t" + "call *(%%edx)\n\t" /* safe to not cleanup esp */ + "movl %%eax, %0" + : "=g"(result) /* %0 */ + : "g"(that), /* %1 */ + "g"(index), /* %2 */ + "g"(paramCount), /* %3 */ + "g"(params), /* %4 */ + "g"(fn_count), /* %5 */ + "g"(fn_copy) /* %6 */ + : "ax", "cx", "dx", "memory"); + + return result; +} + +#endif +/***************************************************************************/ + +int main() { + nsXPCVariant params1[2] = {1, 2}; + nsXPCVariant params2[2] = {2, 4}; + nsXPCVariant params3[2] = {3, 6}; + + foo* a = new bar(); + + // printf("calling via C++...\n"); + // docall(a, 12, 24); + + printf("calling via ASM...\n"); + DoInvoke(a, 1, 2, params1); + DoInvoke(a, 2, 2, params2); + DoInvoke(a, 3, 2, params3); + + return 0; +} diff --git a/xpcom/reflect/xptcall/md/test/mk_invoke.bat b/xpcom/reflect/xptcall/md/test/mk_invoke.bat new file mode 100755 index 0000000000..10a9be51de --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/mk_invoke.bat @@ -0,0 +1,9 @@ +@echo off +@echo deleing old output +if exist invoke_test.obj del invoke_test.obj > NUL +if exist invoke_test.ilk del invoke_test.ilk > NUL +if exist *.pdb del *.pdb > NUL +if exist invoke_test.exe del invoke_test.exe > NUL + +@echo building... +cl /nologo -Zi -DWIN32 invoke_test.cpp
\ No newline at end of file diff --git a/xpcom/reflect/xptcall/md/test/mk_stub.bat b/xpcom/reflect/xptcall/md/test/mk_stub.bat new file mode 100755 index 0000000000..f9af17affe --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/mk_stub.bat @@ -0,0 +1,9 @@ +@echo off +@echo deleing old output +if exist stub_test.obj del stub_test.obj > NUL +if exist stub_test.ilk del stub_test.ilk > NUL +if exist *.pdb del *.pdb > NUL +if exist stub_test.exe del stub_test.exe > NUL + +@echo building... +cl /nologo -Zi -DWIN32 stub_test.cpp
\ No newline at end of file diff --git a/xpcom/reflect/xptcall/md/test/moz.build b/xpcom/reflect/xptcall/md/test/moz.build new file mode 100644 index 0000000000..f31bcf64a3 --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/moz.build @@ -0,0 +1,11 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +SimplePrograms( + [ + "stub_test", + ] +) diff --git a/xpcom/reflect/xptcall/md/test/stub_test.cpp b/xpcom/reflect/xptcall/md/test/stub_test.cpp new file mode 100644 index 0000000000..c83eb93ccc --- /dev/null +++ b/xpcom/reflect/xptcall/md/test/stub_test.cpp @@ -0,0 +1,209 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <stdio.h> + +typedef unsigned nsresult; +typedef unsigned uint32_t; +typedef unsigned nsXPCVariant; + +#if defined(WIN32) +# define NS_IMETHOD virtual nsresult __stdcall +# define NS_IMETHODIMP nsresult __stdcall +#else +# define NS_IMETHOD virtual nsresult +# define NS_IMETHODIMP nsresult +#endif + +class base { + public: + NS_IMETHOD ignored() = 0; +}; + +class foo : public base { + public: + NS_IMETHOD callme1(int i, int j) = 0; + NS_IMETHOD callme2(int i, int j) = 0; + NS_IMETHOD callme3(int i, int j) = 0; +}; + +class bar : public foo { + public: + NS_IMETHOD ignored() override; + NS_IMETHOD callme1(int i, int j) override; + NS_IMETHOD callme2(int i, int j) override; + NS_IMETHOD callme3(int i, int j) override; +}; + +class baz : public base { + public: + NS_IMETHOD ignored() override; + NS_IMETHOD callme1() override; + NS_IMETHOD callme2() override; + NS_IMETHOD callme3() override; + void setfoo(foo* f) { other = f; } + + foo* other; +}; +NS_IMETHODIMP baz::ignored() { return 0; } + +NS_IMETHODIMP bar::ignored() { return 0; } + +NS_IMETHODIMP bar::callme1(int i, int j) { + printf("called bar::callme1 with: %d %d\n", i, j); + return 15; +} + +NS_IMETHODIMP bar::callme2(int i, int j) { + printf("called bar::callme2 with: %d %d\n", i, j); + return 25; +} + +NS_IMETHODIMP bar::callme3(int i, int j) { + printf("called bar::callme3 with: %d %d\n", i, j); + return 35; +} + +void docall(foo* f, int i, int j) { f->callme1(i, j); } + +/***************************************************************************/ +#if defined(WIN32) + +static int __stdcall PrepareAndDispatch(baz* self, uint32_t methodIndex, + uint32_t* args, + uint32_t* stackBytesToPop) { + fprintf(stdout, "PrepareAndDispatch (%p, %d, %p)\n", (void*)self, methodIndex, + (void*)args); + foo* a = self->other; + int p1 = (int)*args; + int p2 = (int)*(args + 1); + int out = 0; + switch (methodIndex) { + case 1: + out = a->callme1(p1, p2); + break; + case 2: + out = a->callme2(p1, p2); + break; + case 3: + out = a->callme3(p1, p2); + break; + } + *stackBytesToPop = 2 * 4; + return out; +} + +# ifndef __GNUC__ +static __declspec(naked) void SharedStub(void) { + __asm { + push ebp // set up simple stack frame + mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args + push ecx // make room for a ptr + lea eax, [ebp-4] // pointer to stackBytesToPop + push eax + lea ecx, [ebp+16] // pointer to args + push ecx + mov edx, [ebp+4] // vtbl_index + push edx + mov eax, [ebp+12] // this + push eax + call PrepareAndDispatch + mov edx, [ebp+8] // return address + mov ecx, [ebp-4] // stackBytesToPop + add ecx, 12 // for this, the index, and ret address + mov esp, ebp + pop ebp + add esp, ecx // fix up stack pointer + jmp edx // simulate __stdcall return + } +} + +// these macros get expanded (many times) in the file #included below +# define STUB_ENTRY(n) \ + __declspec(naked) nsresult __stdcall baz::callme##n() { \ + __asm push n __asm jmp SharedStub \ + } + +# else /* __GNUC__ */ + +# define STUB_ENTRY(n) \ + nsresult __stdcall baz::callme##n() { \ + uint32_t *args, stackBytesToPop; \ + int result = 0; \ + baz* obj; \ + __asm__ __volatile__( \ + "leal 0x0c(%%ebp), %0\n\t" /* args */ \ + "movl 0x08(%%ebp), %1\n\t" /* this */ \ + : "=r"(args), "=r"(obj)); \ + result = PrepareAndDispatch(obj, n, args, &stackBytesToPop); \ + fprintf(stdout, "stub returning: %d\n", result); \ + fprintf(stdout, "bytes to pop: %d\n", stackBytesToPop); \ + return result; \ + } + +# endif /* ! __GNUC__ */ + +#else +/***************************************************************************/ +// just Linux_x86 now. Add other later... + +static int PrepareAndDispatch(baz* self, uint32_t methodIndex, uint32_t* args) { + foo* a = self->other; + int p1 = (int)*args; + int p2 = (int)*(args + 1); + switch (methodIndex) { + case 1: + a->callme1(p1, p2); + break; + case 2: + a->callme2(p1, p2); + break; + case 3: + a->callme3(p1, p2); + break; + } + return 1; +} + +# define STUB_ENTRY(n) \ + nsresult baz::callme##n() { \ + void* method = PrepareAndDispatch; \ + nsresult result; \ + __asm__ __volatile__( \ + "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \ + "pushl %%ecx\n\t" \ + "pushl $" #n \ + "\n\t" /* method index */ \ + "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \ + "pushl %%ecx\n\t" \ + "call *%%edx" /* PrepareAndDispatch */ \ + : "=a"(result) /* %0 */ \ + : "d"(method) /* %1 */ \ + : "memory"); \ + return result; \ + } + +#endif +/***************************************************************************/ + +STUB_ENTRY(1) +STUB_ENTRY(2) +STUB_ENTRY(3) + +int main() { + foo* a = new bar(); + baz* b = new baz(); + + /* here we make the global 'check for alloc failure' checker happy */ + if (!a || !b) return 1; + + foo* c = (foo*)b; + + b->setfoo(a); + c->callme1(1, 2); + c->callme2(2, 4); + c->callme3(3, 6); + + return 0; +} diff --git a/xpcom/reflect/xptcall/md/unix/moz.build b/xpcom/reflect/xptcall/md/unix/moz.build new file mode 100644 index 0000000000..e462ad0938 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/moz.build @@ -0,0 +1,282 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +if CONFIG["OS_ARCH"] == "Darwin": + SOURCES += [ + "xptcinvoke_darwin.cpp", + "xptcstubs_darwin.cpp", + ] + if CONFIG["TARGET_CPU"] == "ppc": + SOURCES += [ + "!xptcstubs_asm_ppc_darwin.s", + "xptcinvoke_asm_ppc_rhapsody.s", + ] + if CONFIG["TARGET_CPU"] == "x86_64": + SOURCES += [ + "xptcinvoke_asm_x86_64_unix.S", + ] + if CONFIG["TARGET_CPU"] == "aarch64": + SOURCES += [ + "xptcinvoke_asm_aarch64.S", + "xptcstubs_asm_aarch64.S", + ] + +if CONFIG["OS_ARCH"] == "GNU": + if CONFIG["TARGET_CPU"] == "x86": + SOURCES += ["xptcinvoke_gcc_x86_unix.cpp", "xptcstubs_gcc_x86_unix.cpp"] + +if CONFIG["OS_ARCH"] in ( + "Linux", + "Bitrig", + "DragonFly", + "FreeBSD", + "NetBSD", + "OpenBSD", + "SunOS", +) or CONFIG["OS_ARCH"].startswith("GNU_"): + if CONFIG["TARGET_CPU"] == "x86_64": + SOURCES += [ + "xptcinvoke_asm_x86_64_unix.S", + "xptcinvoke_x86_64_unix.cpp", + "xptcstubs_x86_64_linux.cpp", + ] + elif CONFIG["TARGET_CPU"] == "x86": + SOURCES += ["xptcinvoke_gcc_x86_unix.cpp", "xptcstubs_gcc_x86_unix.cpp"] + +if CONFIG["OS_ARCH"] in ("Linux", "FreeBSD"): + if CONFIG["TARGET_CPU"] == "ia64": + SOURCES += [ + "xptcinvoke_asm_ipf64.s", + "xptcinvoke_ipf64.cpp", + "xptcstubs_asm_ipf64.s", + "xptcstubs_ipf64.cpp", + ] + +if CONFIG["TARGET_CPU"] == "Alpha": + if CONFIG["OS_ARCH"] in ("Linux", "FreeBSD", "NetBSD"): + SOURCES += [ + "xptcinvoke_linux_alpha.cpp", + "xptcstubs_linux_alpha.cpp", + ] + elif CONFIG["OS_ARCH"] == "OpenBSD": + SOURCES += [ + "xptcinvoke_alpha_openbsd.cpp", + "xptcstubs_alpha_openbsd.cpp", + ] + +if CONFIG["TARGET_CPU"] == "arm": + if CONFIG["OS_ARCH"] == "Linux": + SOURCES += ["xptcinvoke_arm.cpp", "xptcstubs_arm.cpp"] + CXXFLAGS += ["-O2"] + elif CONFIG["OS_ARCH"] == "NetBSD": + SOURCES += [ + "xptcinvoke_arm_netbsd.cpp", + "xptcstubs_arm_netbsd.cpp", + ] + +if CONFIG["TARGET_CPU"] == "arm" and CONFIG["OS_ARCH"] in ("Bitrig", "OpenBSD"): + SOURCES += [ + "xptcinvoke_arm_openbsd.cpp", + "xptcstubs_arm_openbsd.cpp", + ] + +if CONFIG["OS_ARCH"] == "HP-UX": + if CONFIG["CC"] != "gcc": + if CONFIG["TARGET_CPU"] == "ia64": + SOURCES += [ + "xptcinvoke_asm_ipf32.s", + "xptcinvoke_ipf32.cpp", + "xptcstubs_asm_ipf32.s", + "xptcstubs_ipf32.cpp", + ] + else: + SOURCES += [ + "xptcinvoke_asm_pa32.s", + "xptcinvoke_pa32.cpp", + "xptcstubs_asm_pa32.s", + "xptcstubs_pa32.cpp", + ] + +if CONFIG["OS_ARCH"] == "Linux": + if CONFIG["TARGET_CPU"] == "hppa": + if CONFIG["CC_TYPE"] in ("clang", "gcc"): + SOURCES += [ + "xptcinvoke_asm_parisc_linux.s", + "xptcinvoke_pa32.cpp", + "xptcstubs_asm_parisc_linux.s", + "xptcstubs_pa32.cpp", + ] + elif CONFIG["COMPILE_ENVIRONMENT"]: + error("Unknown C++ compiler, xptcall assembly will probably be incorrect.") + +if CONFIG["OS_ARCH"] in ("Linux", "FreeBSD", "NetBSD", "OpenBSD"): + if CONFIG["TARGET_CPU"] == "aarch64": + SOURCES += [ + "xptcinvoke_aarch64.cpp", + "xptcinvoke_asm_aarch64.S", + "xptcstubs_aarch64.cpp", + "xptcstubs_asm_aarch64.S", + ] + if CONFIG["TARGET_CPU"] == "mips64": + SOURCES += [ + "xptcinvoke_asm_mips64.S", + "xptcinvoke_mips64.cpp", + "xptcstubs_asm_mips64.S", + "xptcstubs_mips64.cpp", + ] + if CONFIG["CC_TYPE"] == "clang": + ASFLAGS += [ + "-fno-integrated-as", + ] + if CONFIG["TARGET_CPU"] == "mips32": + SOURCES += [ + "xptcinvoke_asm_mips.S", + "xptcinvoke_mips.cpp", + "xptcstubs_asm_mips.S", + "xptcstubs_mips.cpp", + ] + if CONFIG["CC_TYPE"] == "clang": + ASFLAGS += [ + "-fno-integrated-as", + ] + +if CONFIG["OS_ARCH"] == "AIX": + if CONFIG["HAVE_64BIT_BUILD"]: + SOURCES += [ + "!xptcstubs_asm_ppc_aix64.s", + "xptcinvoke_asm_ppc_aix64.s", + "xptcinvoke_ppc_aix64.cpp", + "xptcstubs_ppc_aix64.cpp", + ] + else: + SOURCES += [ + "!xptcstubs_asm_ppc_aix.s", + "xptcinvoke_ppc_aix.cpp", + "xptcstubs_ppc_aix.cpp", + ] + if CONFIG["AIX_OBJMODEL"] == "ibm": + SOURCES += [ + "xptcinvoke_asm_ppc_ibmobj_aix.s", + ] + else: + SOURCES += [ + "xptcinvoke_asm_ppc_aix.s", + ] + +if CONFIG["TARGET_CPU"] == "ppc": + if CONFIG["OS_ARCH"] in ("Linux", "FreeBSD"): + SOURCES += [ + "xptcinvoke_asm_ppc_linux.S", + "xptcinvoke_ppc_linux.cpp", + "xptcstubs_asm_ppc_linux.S", + "xptcstubs_ppc_linux.cpp", + ] + +if CONFIG["TARGET_CPU"] == "ppc64": + if CONFIG["OS_ARCH"] in ("Linux", "FreeBSD"): + SOURCES += [ + "xptcinvoke_asm_ppc64_linux.S", + "xptcinvoke_ppc64_linux.cpp", + "xptcstubs_asm_ppc64_linux.S", + "xptcstubs_ppc64_linux.cpp", + ] + if CONFIG["CC_TYPE"] == "clang": + ASFLAGS += [ + "-fno-integrated-as", + ] + +if CONFIG["OS_ARCH"] == "OpenBSD" and CONFIG["TARGET_CPU"] == "ppc": + SOURCES += [ + "xptcinvoke_asm_ppc_openbsd.S", + "xptcinvoke_ppc_openbsd.cpp", + "xptcstubs_asm_ppc_openbsd.S", + "xptcstubs_ppc_openbsd.cpp", + ] + +if CONFIG["OS_ARCH"] == "Linux" and CONFIG["TARGET_CPU"] == "sparc": + SOURCES += [ + "xptcinvoke_asm_sparc_linux_GCC3.s", + "xptcinvoke_sparc_solaris.cpp", + "xptcstubs_asm_sparc_solaris.s", + "xptcstubs_sparc_solaris.cpp", + ] + +if CONFIG["OS_ARCH"] == "NetBSD" and CONFIG["TARGET_CPU"] == "sparc": + SOURCES += [ + "xptcinvoke_asm_sparc_netbsd.s", + "xptcinvoke_sparc_netbsd.cpp", + "xptcstubs_asm_sparc_netbsd.s", + "xptcstubs_sparc_netbsd.cpp", + ] + +if CONFIG["OS_ARCH"] == "OpenBSD" and CONFIG["TARGET_CPU"] == "sparc": + SOURCES += [ + "xptcinvoke_asm_sparc_openbsd.s", + "xptcinvoke_sparc_openbsd.cpp", + "xptcstubs_asm_sparc_openbsd.s", + "xptcstubs_sparc_openbsd.cpp", + ] + +if ( + CONFIG["OS_ARCH"] in ("OpenBSD", "FreeBSD", "Linux", "SunOS") + and CONFIG["TARGET_CPU"] == "sparc64" +): + SOURCES += [ + "xptcinvoke_asm_sparc64_openbsd.s", + "xptcinvoke_sparc64_openbsd.cpp", + "xptcstubs_asm_sparc64_openbsd.s", + "xptcstubs_sparc64_openbsd.cpp", + ] + +if CONFIG["OS_ARCH"] == "Linux": + if CONFIG["TARGET_CPU"] == "s390": + SOURCES += [ + "xptcinvoke_linux_s390.cpp", + "xptcstubs_linux_s390.cpp", + ] + CXXFLAGS += [ + "-fno-strict-aliasing", + "-fno-inline", + "-fomit-frame-pointer", + "-mbackchain", + ] + elif CONFIG["TARGET_CPU"] == "s390x": + SOURCES += [ + "xptcinvoke_linux_s390x.cpp", + "xptcstubs_linux_s390x.cpp", + ] + CXXFLAGS += [ + "-fno-strict-aliasing", + "-fno-inline", + "-fomit-frame-pointer", + "-mbackchain", + ] + if CONFIG["CC_TYPE"] == "clang": + CXXFLAGS += [ + "-fno-integrated-as", + ] + +if CONFIG["OS_ARCH"] in ("Linux", "OpenBSD") and CONFIG["TARGET_CPU"] == "riscv64": + SOURCES += [ + "xptcinvoke_asm_riscv64.S", + "xptcinvoke_riscv64.cpp", + "xptcstubs_asm_riscv64.S", + "xptcstubs_riscv64.cpp", + ] + +if CONFIG["OS_ARCH"] == "Linux" and CONFIG["TARGET_CPU"] == "loongarch64": + SOURCES += [ + "xptcinvoke_asm_loongarch64.S", + "xptcinvoke_loongarch64.cpp", + "xptcstubs_asm_loongarch64.S", + "xptcstubs_loongarch64.cpp", + ] + +FINAL_LIBRARY = "xul" + +LOCAL_INCLUDES += [ + "../..", +] diff --git a/xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp b/xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp new file mode 100644 index 0000000000..9139d4b2aa --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp @@ -0,0 +1,66 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* this code contributed by Bert Driehuis <bert_driehuis@nl.compuware.com> */ + +#include <stdio.h> + +// Try to determine the vtable layout generated by G++ +// Produces the offset at which the first vtable entry can be +// found, and the factor to apply for subsequent entries on stdout. +// Example output: +// #define GCC_VTABLE_START 0xc +// #define GCC_VTABLE_FACTOR 0x8 + +class test { +public: + virtual int t1(void); + virtual int t2(void); + int x; +}; + +test::test() { this->x = 0x12121212; }; + +int test::t1(void) { return 1; } +int test::t2(void) { return 2; } + +void die(char *x) { + fprintf(stderr, "%s\n", x); + exit(1); +} + +int +main() +{ + int i; + test *t = new test(); + int *tp = (int *) t; + int off1 = -1; + int off2 = -1; + int factor; + int factorshift; + + if (*tp++ != 0x12121212) + die("Integer element test::x not found!"); + tp = (int *) *tp; + for (i = 0; i < 10; i++) { + if (tp[i] == (int) t->t1) + off1 = i; + if (tp[i] == (int) t->t2) + off2 = i; + } + if (off1 == -1 || off2 == -1) + die("Could not determine offset into vtable!"); + factor = (off2 - off1) * 4; + factorshift = -1; + while (factor) { + factorshift++; + factor >>= 1; + } + printf("/* Automatically generated by vtable_layout_x86.cpp */\n"); + printf("#define GCC_VTABLE_START\t0x%x\n", off1 * 4); + printf("#define GCC_VTABLE_FACTOR\t0x%x\n", (off2 - off1) * 4); + printf("#define GCC_VTABLE_SHIFT\t0x%x\n", factorshift); + exit(0); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h b/xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h new file mode 100644 index 0000000000..5d6e71c23c --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h @@ -0,0 +1,16 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Special include file for xptc*_gcc_x86_unix.cpp */ + +// +// this may improve the static function calls, but may not. +// + +#ifdef MOZ_NEED_LEADING_UNDERSCORE +#define SYMBOL_UNDERSCORE "_" +#else +#define SYMBOL_UNDERSCORE +#endif diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp new file mode 100644 index 0000000000..385cba17ad --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp @@ -0,0 +1,168 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#if !defined(__aarch64__) +#error "This code is for Linux AArch64 only." +#endif + + +/* "Procedure Call Standard for the ARM 64-bit Architecture" document, sections + * "5.4 Parameter Passing" and "6.1.2 Procedure Calling" contain all the + * needed information. + * + * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf + */ + +#ifndef __AARCH64EL__ +#error "Only little endian compatibility was tested" +#endif + +// The AAPCS doesn't require argument widening, but Apple's calling convention +// does. If we are really fortunate, the compiler will clean up all the +// copying for us. +template<typename T> +inline uint64_t normalize_arg(T value) { + return (uint64_t)value; +} + +template<> +inline uint64_t normalize_arg(float value) { + uint64_t result = 0; + memcpy(&result, &value, sizeof(value)); + return result; +} + +template<> +inline uint64_t normalize_arg(double value) { + uint64_t result = 0; + memcpy(&result, &value, sizeof(value)); + return result; +} + +/* + * Allocation of function arguments to their appropriate place in registers + * if possible and then to the stack. Handling of 'that' argument which + * goes to register r0 is handled separately and does not belong here. + * + * Note that we are handling integer arguments and floating-point arguments + * identically, depending on which register area is passed to this function. + * + * 'reg_args' - pointer to the current position in the buffer, + * corresponding to the register arguments. + * 'reg_args_end' - pointer to the end of the registers argument + * buffer. + * 'stack_args' - pointer to the current position in the buffer, + * corresponding to the arguments on stack. + * 'data' - typed data to put on the stack. + */ +template<typename T> +static inline void alloc_arg(uint64_t* ®_args, + uint64_t* reg_args_end, + void* &stack_args, + T* data) +{ + if (reg_args < reg_args_end) { + *reg_args = normalize_arg(*data); + reg_args++; + } else { + // According to the ABI, types that are smaller than 8 bytes are + // passed in registers or 8-byte stack slots. This rule is only + // partially true on Apple platforms, where types smaller than 8 + // bytes occupy only the space they require on the stack and + // their stack slot must be properly aligned. +#ifdef __APPLE__ + const size_t aligned_size = sizeof(T); +#else + const size_t aligned_size = 8; +#endif + // Ensure the pointer is aligned for the type + uintptr_t addr = (reinterpret_cast<uintptr_t>(stack_args) + aligned_size - 1) & ~(aligned_size - 1); + memcpy(reinterpret_cast<void*>(addr), data, sizeof(T)); + // Point the stack to the next slot. + stack_args = reinterpret_cast<void*>(addr + aligned_size); + } +} + +extern "C" void +invoke_copy_to_stack(uint64_t* stk, uint64_t *end, + uint32_t paramCount, nsXPTCVariant* s) +{ + uint64_t* ireg_args = stk; + uint64_t* ireg_end = ireg_args + 8; + // Pun on integer and floating-point registers being the same size. + uint64_t* freg_args = ireg_end; + uint64_t* freg_end = freg_args + 8; + void* stack_args = freg_end; + + // leave room for 'that' argument in x0 + ++ireg_args; + + for (uint32_t i = 0; i < paramCount; i++, s++) { + if (s->IsIndirect()) { + void* ptr = &s->val; + alloc_arg(ireg_args, ireg_end, stack_args, &ptr); + } else { + switch (s->type) { + case nsXPTType::T_FLOAT: + alloc_arg(freg_args, freg_end, stack_args, &s->val.f); + break; + case nsXPTType::T_DOUBLE: + alloc_arg(freg_args, freg_end, stack_args, &s->val.d); + break; + case nsXPTType::T_I8: + alloc_arg(ireg_args, ireg_end, stack_args, &s->val.i8); + break; + case nsXPTType::T_I16: + alloc_arg(ireg_args, ireg_end, stack_args, &s->val.i16); + break; + case nsXPTType::T_I32: + alloc_arg(ireg_args, ireg_end, stack_args, &s->val.i32); + break; + case nsXPTType::T_I64: + alloc_arg(ireg_args, ireg_end, stack_args, &s->val.i64); + break; + case nsXPTType::T_U8: + alloc_arg(ireg_args, ireg_end, stack_args, &s->val.u8); + break; + case nsXPTType::T_U16: + alloc_arg(ireg_args, ireg_end, stack_args, &s->val.u16); + break; + case nsXPTType::T_U32: + alloc_arg(ireg_args, ireg_end, stack_args, &s->val.u32); + break; + case nsXPTType::T_U64: + alloc_arg(ireg_args, ireg_end, stack_args, &s->val.u64); + break; + case nsXPTType::T_BOOL: + alloc_arg(ireg_args, ireg_end, stack_args, &s->val.b); + break; + case nsXPTType::T_CHAR: + alloc_arg(ireg_args, ireg_end, stack_args, &s->val.c); + break; + case nsXPTType::T_WCHAR: + alloc_arg(ireg_args, ireg_end, stack_args, &s->val.wc); + break; + default: + // all the others are plain pointer types + alloc_arg(ireg_args, ireg_end, stack_args, &s->val.p); + break; + } + } + } +} + +extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + return _NS_InvokeByIndex(that, methodIndex, paramCount, params); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp new file mode 100644 index 0000000000..dc111e4358 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp @@ -0,0 +1,144 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +/* Prototype specifies unmangled function name and disables unused warning */ +static void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s) +__asm__("invoke_copy_to_stack") __attribute__((used)); + +static void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer + + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if(s->IsPtrData()) + { + *d = (uint64_t)s->ptr; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : *d = (uint64_t)s->val.i8; break; + case nsXPTType::T_I16 : *d = (uint64_t)s->val.i16; break; + case nsXPTType::T_I32 : *d = (uint64_t)s->val.i32; break; + case nsXPTType::T_I64 : *d = (uint64_t)s->val.i64; break; + case nsXPTType::T_U8 : *d = (uint64_t)s->val.u8; break; + case nsXPTType::T_U16 : *d = (uint64_t)s->val.u16; break; + case nsXPTType::T_U32 : *d = (uint64_t)s->val.u32; break; + case nsXPTType::T_U64 : *d = (uint64_t)s->val.u64; break; + case nsXPTType::T_FLOAT : + if(i < NUM_ARG_REGS) + { + // convert floats to doubles if they are to be passed + // via registers so we can just deal with doubles later + union { uint64_t u64; double d; } t; + t.d = (double)s->val.f; + *d = t.u64; + } + else + // otherwise copy to stack normally + *d = (uint64_t)s->val.u32; + break; + case nsXPTType::T_DOUBLE : *d = (uint64_t)s->val.u64; break; + case nsXPTType::T_BOOL : *d = (uint64_t)s->val.b; break; + case nsXPTType::T_CHAR : *d = (uint64_t)s->val.c; break; + case nsXPTType::T_WCHAR : *d = (uint64_t)s->val.wc; break; + default: + // all the others are plain pointer types + *d = (uint64_t)s->val.p; + break; + } + } +} + +/* + * EXPORT_XPCOM_API(nsresult) + * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + * uint32_t paramCount, nsXPTCVariant* params) + */ +__asm__( + "#### NS_InvokeByIndex ####\n" +".text\n\t" + ".align 5\n\t" + ".globl NS_InvokeByIndex\n\t" + ".ent NS_InvokeByIndex\n" +"NS_InvokeByIndex:\n\t" + ".frame $15,32,$26,0\n\t" + ".mask 0x4008000,-32\n\t" + "ldgp $29,0($27)\n" +"$NS_InvokeByIndex..ng:\n\t" + "subq $30,32,$30\n\t" + "stq $26,0($30)\n\t" + "stq $15,8($30)\n\t" + "bis $30,$30,$15\n\t" + ".prologue 1\n\t" + + /* + * Allocate enough stack space to hold the greater of 6 or "paramCount"+1 + * parameters. (+1 for "this" pointer) Room for at least 6 parameters + * is required for storage of those passed via registers. + */ + + "bis $31,5,$2\n\t" /* count = MAX(5, "paramCount") */ + "cmplt $2,$18,$1\n\t" + "cmovne $1,$18,$2\n\t" + "s8addq $2,16,$1\n\t" /* room for count+1 params (8 bytes each) */ + "bic $1,15,$1\n\t" /* stack space is rounded up to 0 % 16 */ + "subq $30,$1,$30\n\t" + + "stq $16,0($30)\n\t" /* save "that" (as "this" pointer) */ + "stq $17,16($15)\n\t" /* save "methodIndex" */ + + "addq $30,8,$16\n\t" /* pass stack pointer */ + "bis $18,$18,$17\n\t" /* pass "paramCount" */ + "bis $19,$19,$18\n\t" /* pass "params" */ + "bsr $26,$invoke_copy_to_stack..ng\n\t" /* call invoke_copy_to_stack */ + + /* + * Copy the first 6 parameters to registers and remove from stack frame. + * Both the integer and floating point registers are set for each parameter + * except the first which is the "this" pointer. (integer only) + * The floating point registers are all set as doubles since the + * invoke_copy_to_stack function should have converted the floats. + */ + "ldq $16,0($30)\n\t" /* integer registers */ + "ldq $17,8($30)\n\t" + "ldq $18,16($30)\n\t" + "ldq $19,24($30)\n\t" + "ldq $20,32($30)\n\t" + "ldq $21,40($30)\n\t" + "ldt $f17,8($30)\n\t" /* floating point registers */ + "ldt $f18,16($30)\n\t" + "ldt $f19,24($30)\n\t" + "ldt $f20,32($30)\n\t" + "ldt $f21,40($30)\n\t" + + "addq $30,48,$30\n\t" /* remove params from stack */ + + /* + * Call the virtual function with the constructed stack frame. + */ + "bis $16,$16,$1\n\t" /* load "this" */ + "ldq $2,16($15)\n\t" /* load "methodIndex" */ + "ldq $1,0($1)\n\t" /* load vtable */ + "s8addq $2,$31,$2\n\t" /* vtable index = "methodIndex" * 8 */ + "addq $1,$2,$1\n\t" + "ldq $27,0($1)\n\t" /* load address of function */ + "jsr $26,($27),0\n\t" /* call virtual function */ + "ldgp $29,0($26)\n\t" + + "bis $15,$15,$30\n\t" + "ldq $26,0($30)\n\t" + "ldq $15,8($30)\n\t" + "addq $30,32,$30\n\t" + "ret $31,($26),1\n\t" + ".end NS_InvokeByIndex" + ); diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp new file mode 100644 index 0000000000..39a6b406f4 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp @@ -0,0 +1,417 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#include "mozilla/Compiler.h" + +#if !defined(__arm__) || !(defined(LINUX) || defined(ANDROID) || defined(XP_IOS)) +#error "This code is for Linux/iOS ARM only. Check that it works on your system, too.\nBeware that this code is highly compiler dependent." +#endif + +#if MOZ_IS_GCC +#if defined(__ARM_EABI__) && !defined(__ARM_PCS_VFP) && !defined(__ARM_PCS) +#error "Can't identify floating point calling conventions.\nPlease ensure that your toolchain defines __ARM_PCS or __ARM_PCS_VFP." +#endif +#endif + +#ifndef __ARM_PCS_VFP + +/* This function copies a 64-bits word from dw to the given pointer in + * a buffer delimited by start and end, possibly wrapping around the + * buffer boundaries, and/or properly aligning the data at 64-bits word + * boundaries (for EABI). + * start and end are both assumed to be 64-bits aligned. + * Returns a pointer to the second 32-bits word copied (to accomodate + * the invoke_copy_to_stack loop). + */ +static uint32_t * +copy_double_word(uint32_t *start, uint32_t *current, uint32_t *end, uint64_t *dw) +{ +#ifdef __ARM_EABI__ + /* Aligning the pointer for EABI */ + current = (uint32_t *)(((uint32_t)current + 7) & ~7); + /* Wrap when reaching the end of the buffer */ + if (current == end) current = start; +#else + /* On non-EABI, 64-bits values are not aligned and when we reach the end + * of the buffer, we need to write half of the data at the end, and the + * other half at the beginning. */ + if (current == end - 1) { + *current = ((uint32_t*)dw)[0]; + *start = ((uint32_t*)dw)[1]; + return start; + } +#endif + + *((uint64_t*) current) = *dw; + return current + 1; +} + +/* See stack_space comment in NS_InvokeByIndex to see why this needs not to + * be static on DEBUG builds. */ +#ifndef DEBUG +static +#endif +void +invoke_copy_to_stack(uint32_t* stk, uint32_t *end, + uint32_t paramCount, nsXPTCVariant* s) +{ + /* The stack buffer is 64-bits aligned. The end argument points to its end. + * The caller is assumed to create a stack buffer of at least four 32-bits + * words. + * We use the last three 32-bit words to store the values for r1, r2 and r3 + * for the method call, i.e. the first words for arguments passing. + */ + uint32_t *d = end - 3; + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + /* Wrap when reaching the end of the stack buffer */ + if (d == end) d = stk; + NS_ASSERTION(d >= stk && d < end, + "invoke_copy_to_stack is copying outside its given buffer"); + if(s->IsIndirect()) + { + *((void**)d) = &s->val; + continue; + } + // According to the ARM EABI, integral types that are smaller than a word + // are to be sign/zero-extended to a full word and treated as 4-byte values. + + switch(s->type) + { + case nsXPTType::T_I8 : *((int32_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : + d = copy_double_word(stk, d, end, (uint64_t *)&s->val.i64); + break; + case nsXPTType::T_U8 : *((uint32_t*)d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : + d = copy_double_word(stk, d, end, (uint64_t *)&s->val.u64); + break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : + d = copy_double_word(stk, d, end, (uint64_t *)&s->val.d); + break; + case nsXPTType::T_BOOL : *((int32_t*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((int32_t*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((int32_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} + +typedef nsresult (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t); + +// Avoid AddressSanitizer instrumentation for the next function because it +// depends on __builtin_alloca behavior and alignment that cannot be relied on +// once the function is compiled with a version of ASan that has dynamic-alloca +// instrumentation enabled. + +MOZ_ASAN_IGNORE +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + +/* This is to call a given method of class that. + * The parameters are in params, the number is in paramCount. + * The routine will issue calls to count the number of words + * required for argument passing and to copy the arguments to + * the stack. + * ACPS passes the first 3 params in r1-r3 (with exceptions for 64-bits + * arguments), and the remaining goes onto the stack. + * We allocate a buffer on the stack for a "worst case" estimate of how much + * stack might be needed for EABI, i.e. twice the number of parameters. + * The end of this buffer will be used to store r1 to r3, so that the start + * of the stack is the remaining parameters. + * The magic here is to call the method with "that" and three 32-bits + * arguments corresponding to r1-r3, so that the compiler generates the + * proper function call. The stack will also contain the remaining arguments. + * + * !!! IMPORTANT !!! + * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented + * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])! + * + */ + + vtable_func *vtable, func; + int base_size = (paramCount > 1) ? paramCount : 2; + +/* !!! IMPORTANT !!! + * On DEBUG builds, the NS_ASSERTION used in invoke_copy_to_stack needs to use + * the stack to pass the 5th argument to NS_DebugBreak. When invoke_copy_to_stack + * is inlined, this can result, depending on the compiler and flags, in the + * stack pointer not pointing at stack_space when the method is called at the + * end of this function. More generally, any function call requiring stack + * allocation of arguments is unsafe to be inlined in this function. + */ + uint32_t *stack_space = (uint32_t *) __builtin_alloca(base_size * 8); + + invoke_copy_to_stack(stack_space, &stack_space[base_size * 2], + paramCount, params); + + vtable = *reinterpret_cast<vtable_func **>(that); + func = vtable[methodIndex]; + + return func(that, stack_space[base_size * 2 - 3], + stack_space[base_size * 2 - 2], + stack_space[base_size * 2 - 1]); +} + +#else /* __ARM_PCS_VFP */ + +/* "Procedure Call Standard for the ARM Architecture" document, sections + * "5.5 Parameter Passing" and "6.1.2 Procedure Calling" contain all the + * needed information. + * + * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf + */ + +#if defined(__thumb__) && !defined(__thumb2__) +#error "Thumb1 is not supported" +#endif + +#ifndef __ARMEL__ +#error "Only little endian compatibility was tested" +#endif + +/* + * Allocation of integer function arguments initially to registers r1-r3 + * and then to stack. Handling of 'this' argument which goes to r0 registers + * is handled separately and does not belong to these two inline functions. + * + * The doubleword arguments are allocated to even:odd + * register pairs or get aligned at 8-byte boundary on stack. The "holes" + * which may appear as a result of this realignment remain unused. + * + * 'ireg_args' - pointer to the current position in the buffer, + * corresponding to the register arguments + * 'stack_args' - pointer to the current position in the buffer, + * corresponding to the arguments on stack + * 'end' - pointer to the end of the registers argument + * buffer (it is guaranteed to be 8-bytes aligned) + */ + +static inline void copy_word(uint32_t* &ireg_args, + uint32_t* &stack_args, + uint32_t* end, + uint32_t data) +{ + if (ireg_args < end) { + *ireg_args = data; + ireg_args++; + } else { + *stack_args = data; + stack_args++; + } +} + +static inline void copy_dword(uint32_t* &ireg_args, + uint32_t* &stack_args, + uint32_t* end, + uint64_t data) +{ + if (ireg_args + 1 < end) { + if ((uint32_t)ireg_args & 4) { + ireg_args++; + } + *(uint64_t *)ireg_args = data; + ireg_args += 2; + } else { + ireg_args = end; + if ((uint32_t)stack_args & 4) { + stack_args++; + } + *(uint64_t *)stack_args = data; + stack_args += 2; + } +} + +/* + * Allocation of floating point arguments to VFP registers (s0-s15, d0-d7). + * + * Unlike integer registers allocation, "back-filling" needs to be + * supported. For example, the third floating point argument in the + * following function is going to be allocated to s1 register, back-filling + * the "hole": + * void f(float s0, double d1, float s1) + * + * Refer to the "Procedure Call Standard for the ARM Architecture" document + * for more details. + * + * 'vfp_s_args' - pointer to the current position in the buffer with + * the next unallocated single precision register + * 'vfp_d_args' - pointer to the current position in the buffer with + * the next unallocated double precision register, + * it has the same value as 'vfp_s_args' when back-filling + * is not used + * 'end' - pointer to the end of the vfp registers argument + * buffer (it is guaranteed to be 8-bytes aligned) + * + * Mozilla bugtracker has a test program attached which be used for + * experimenting with VFP registers allocation code and testing its + * correctness: + * https://bugzilla.mozilla.org/show_bug.cgi?id=601914#c19 + */ + +static inline bool copy_vfp_single(float* &vfp_s_args, double* &vfp_d_args, + float* end, float data) +{ + if (vfp_s_args >= end) + return false; + + *vfp_s_args = data; + vfp_s_args++; + if (vfp_s_args < (float *)vfp_d_args) { + // It was the case of back-filling, now the next free single precision + // register should overlap with the next free double precision register + vfp_s_args = (float *)vfp_d_args; + } else if (vfp_s_args > (float *)vfp_d_args) { + // also update the pointer to the next free double precision register + vfp_d_args++; + } + return true; +} + +static inline bool copy_vfp_double(float* &vfp_s_args, double* &vfp_d_args, + float* end, double data) +{ + if (vfp_d_args >= (double *)end) { + // The back-filling continues only so long as no VFP CPRC has been + // allocated to a slot on the stack. Basically no VFP registers can + // be allocated after this point. + vfp_s_args = end; + return false; + } + + if (vfp_s_args == (float *)vfp_d_args) { + // also update the pointer to the next free single precision register + vfp_s_args += 2; + } + *vfp_d_args = data; + vfp_d_args++; + return true; +} + +static void +invoke_copy_to_stack(uint32_t* stk, uint32_t *end, + uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t *ireg_args = end - 3; + float *vfp_s_args = (float *)end; + double *vfp_d_args = (double *)end; + float *vfp_end = vfp_s_args + 16; + + for (uint32_t i = 0; i < paramCount; i++, s++) { + if (s->IsIndirect()) { + copy_word(ireg_args, stk, end, (uint32_t)&s->val); + continue; + } + // According to the ARM EABI, integral types that are smaller than a word + // are to be sign/zero-extended to a full word and treated as 4-byte values + switch (s->type) + { + case nsXPTType::T_FLOAT: + if (!copy_vfp_single(vfp_s_args, vfp_d_args, vfp_end, s->val.f)) { + copy_word(end, stk, end, reinterpret_cast<uint32_t&>(s->val.f)); + } + break; + case nsXPTType::T_DOUBLE: + if (!copy_vfp_double(vfp_s_args, vfp_d_args, vfp_end, s->val.d)) { + copy_dword(end, stk, end, reinterpret_cast<uint64_t&>(s->val.d)); + } + break; + case nsXPTType::T_I8: copy_word(ireg_args, stk, end, s->val.i8); break; + case nsXPTType::T_I16: copy_word(ireg_args, stk, end, s->val.i16); break; + case nsXPTType::T_I32: copy_word(ireg_args, stk, end, s->val.i32); break; + case nsXPTType::T_I64: copy_dword(ireg_args, stk, end, s->val.i64); break; + case nsXPTType::T_U8: copy_word(ireg_args, stk, end, s->val.u8); break; + case nsXPTType::T_U16: copy_word(ireg_args, stk, end, s->val.u16); break; + case nsXPTType::T_U32: copy_word(ireg_args, stk, end, s->val.u32); break; + case nsXPTType::T_U64: copy_dword(ireg_args, stk, end, s->val.u64); break; + case nsXPTType::T_BOOL: copy_word(ireg_args, stk, end, s->val.b); break; + case nsXPTType::T_CHAR: copy_word(ireg_args, stk, end, s->val.c); break; + case nsXPTType::T_WCHAR: copy_word(ireg_args, stk, end, s->val.wc); break; + default: + // all the others are plain pointer types + copy_word(ireg_args, stk, end, reinterpret_cast<uint32_t>(s->val.p)); + break; + } + } +} + +typedef uint32_t (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t); + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + vtable_func *vtable = *reinterpret_cast<vtable_func **>(that); + vtable_func func = vtable[methodIndex]; + // 'register uint32_t result asm("r0")' could be used here, but it does not + // seem to be reliable in all cases: http://gcc.gnu.org/PR46164 + nsresult result; + asm ( + "mov r3, sp\n" + "mov %[stack_space_size], %[param_count_plus_2], lsl #3\n" + "tst r3, #4\n" /* check stack alignment */ + + "add %[stack_space_size], #(4 * 16)\n" /* space for VFP registers */ + "mov r3, %[params]\n" + + "it ne\n" + "addne %[stack_space_size], %[stack_space_size], #4\n" + "sub r0, sp, %[stack_space_size]\n" /* allocate space on stack */ + + "sub r2, %[param_count_plus_2], #2\n" + "mov sp, r0\n" + + "add r1, r0, %[param_count_plus_2], lsl #3\n" + "blx %[invoke_copy_to_stack]\n" + + "add ip, sp, %[param_count_plus_2], lsl #3\n" + "mov r0, %[that]\n" + "ldmdb ip, {r1, r2, r3}\n" + "vldm ip, {d0, d1, d2, d3, d4, d5, d6, d7}\n" + "blx %[func]\n" + + "add sp, sp, %[stack_space_size]\n" /* cleanup stack */ + "mov %[stack_space_size], r0\n" /* it's actually 'result' variable */ + : [stack_space_size] "=&r" (result) + : [func] "r" (func), + [that] "r" (that), + [params] "r" (params), + [param_count_plus_2] "r" (paramCount + 2), + [invoke_copy_to_stack] "r" (invoke_copy_to_stack) + : "cc", "memory", + // Mark all the scratch registers as clobbered because they may be + // modified by the functions, called from this inline assembly block + "r0", "r1", "r2", "r3", "ip", "lr", + "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", + // Also unconditionally mark d16-d31 registers as clobbered even though + // they actually don't exist in vfpv2 and vfpv3-d16 variants. There is + // no way to identify VFP variant using preprocessor at the momemnt + // (see http://gcc.gnu.org/PR46128 for more details), but fortunately + // current versions of gcc do not seem to complain about these registers + // even when this code is compiled with '-mfpu=vfpv3-d16' option. + // If gcc becomes more strict in the future and/or provides a way to + // identify VFP variant, the following d16-d31 registers list needs + // to be wrapped into some #ifdef + "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", + "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31" + ); + return result; +} + +#endif diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp new file mode 100644 index 0000000000..2624c1e892 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp @@ -0,0 +1,181 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +// Remember that these 'words' are 32bit DWORDS + +static uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t result = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + return result; +} + +static void +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; + case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} + +extern "C" +struct my_params_struct { + nsISupports* that; + uint32_t Index; + uint32_t Count; + nsXPTCVariant* params; + uint32_t fn_count; + uint32_t fn_copy; +}; + +XPTC_PUBLIC_API(nsresult) +XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + uint32_t result; + struct my_params_struct my_params; + my_params.that = that; + my_params.Index = methodIndex; + my_params.Count = paramCount; + my_params.params = params; + my_params.fn_copy = (uint32_t) &invoke_copy_to_stack; + my_params.fn_count = (uint32_t) &invoke_count_words; + +/* This is to call a given method of class that. + * The parameters are in params, the number is in paramCount. + * The routine will issue calls to count the number of words + * required for argument passing and to copy the arguments to + * the stack. + * Since APCS passes the first 3 params in r1-r3, we need to + * load the first three words from the stack and correct the stack + * pointer (sp) in the appropriate way. This means: + * + * 1.) more than 3 arguments: load r1-r3, correct sp and remember No. + * of bytes left on the stack in r4 + * + * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope), + * restore sp as if nothing had happened and set the marker r4 to zero. + * + * Afterwards sp will be restored using the value in r4 (which is not a temporary register + * and will be preserved by the function/method called according to APCS [ARM Procedure + * Calling Standard]). + * + * !!! IMPORTANT !!! + * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented + * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])! + * + */ + + __asm__ __volatile__( + "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */ + "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */ + "ldr r0, [%1, #8] \n\t" + "mov lr, pc \n\t" /* call it... */ + "mov pc, ip \n\t" + "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */ + "sub sp, sp, r4 \n\t" /* use stack space for the args... */ + "mov r0, sp \n\t" /* prepare a pointer an the stack */ + "ldr r1, [%1, #8] \n\t" /* =paramCount */ + "ldr r2, [%1, #12] \n\t" /* =params */ + "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */ + "mov lr, pc \n\t" /* copy args to the stack like the */ + "mov pc, ip \n\t" /* compiler would. */ + "ldr r0, [%1] \n\t" /* =that */ + "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */ + "ldr r2, [%1, #4] \n\t" + "add r2, r1, r2, lsl #3\n\t" /* a vtable_entry(x)=8 + (8 bytes * x) */ + "add r2, r2, #8 \n\t" /* with this compilers */ + "ldr r3, [r2] \n\t" /* get virtual offset from vtable */ + "mov r3, r3, lsl #16 \n\t" + "add r0, r0, r3, asr #16\n\t" + "ldr ip, [r2, #4] \n\t" /* get method address from vtable */ + "cmp r4, #12 \n\t" /* more than 3 arguments??? */ + "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */ + "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */ + "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */ + "addle sp, sp, r4 \n\t" /* and restore stack pointer */ + "movle r4, #0 \n\t" /* a mark for restoring sp */ + "mov lr, pc \n\t" /* call mathod */ + "mov pc, ip \n\t" + "add sp, sp, r4 \n\t" /* restore stack pointer */ + "mov %0, r0 \n\t" /* the result... */ + : "=r" (result) + : "r" (&my_params) + : "r0", "r1", "r2", "r3", "r4", "ip", "lr" + ); + + return result; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp new file mode 100644 index 0000000000..60b0574200 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp @@ -0,0 +1,183 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +// Remember that these 'words' are 32bit DWORDS + +static uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t result = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + return result; +} + +static void +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; + case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} + +extern "C" { + struct my_params_struct { + nsISupports* that; + uint32_t Index; + uint32_t Count; + nsXPTCVariant* params; + uint32_t fn_count; + uint32_t fn_copy; + }; +} + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + uint32_t result; + struct my_params_struct my_params; + my_params.that = that; + my_params.Index = methodIndex; + my_params.Count = paramCount; + my_params.params = params; + my_params.fn_copy = (uint32_t) &invoke_copy_to_stack; + my_params.fn_count = (uint32_t) &invoke_count_words; + +/* This is to call a given method of class that. + * The parameters are in params, the number is in paramCount. + * The routine will issue calls to count the number of words + * required for argument passing and to copy the arguments to + * the stack. + * Since APCS passes the first 3 params in r1-r3, we need to + * load the first three words from the stack and correct the stack + * pointer (sp) in the appropriate way. This means: + * + * 1.) more than 3 arguments: load r1-r3, correct sp and remember No. + * of bytes left on the stack in r4 + * + * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope), + * restore sp as if nothing had happened and set the marker r4 to zero. + * + * Afterwards sp will be restored using the value in r4 (which is not a temporary register + * and will be preserved by the function/method called according to APCS [ARM Procedure + * Calling Standard]). + * + * !!! IMPORTANT !!! + * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented + * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])! + * + */ + +#ifdef __GNUC__ + __asm__ __volatile__( + "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */ + "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */ + "ldr r0, [%1, #8] \n\t" + "mov lr, pc \n\t" /* call it... */ + "mov pc, ip \n\t" + "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */ + "sub sp, sp, r4 \n\t" /* use stack space for the args... */ + "mov r0, sp \n\t" /* prepare a pointer an the stack */ + "ldr r1, [%1, #8] \n\t" /* =paramCount */ + "ldr r2, [%1, #12] \n\t" /* =params */ + "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */ + "mov lr, pc \n\t" /* copy args to the stack like the */ + "mov pc, ip \n\t" /* compiler would. */ + "ldr r0, [%1] \n\t" /* =that */ + "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */ + "ldr r2, [%1, #4] \n\t" + "mov r2, r2, lsl #2 \n\t" /* a vtable_entry(x)=8 + (4 bytes * x) */ + "ldr ip, [r1, r2] \n\t" /* get method adress from vtable */ + "cmp r4, #12 \n\t" /* more than 3 arguments??? */ + "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */ + "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */ + "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */ + "addle sp, sp, r4 \n\t" /* and restore stack pointer */ + "movle r4, #0 \n\t" /* a mark for restoring sp */ + "ldr r0, [%1, #0] \n\t" /* get (self) */ + "mov lr, pc \n\t" /* call mathod */ + "mov pc, ip \n\t" + "add sp, sp, r4 \n\t" /* restore stack pointer */ + "mov %0, r0 \n\t" /* the result... */ + : "=r" (result) + : "r" (&my_params), "m" (my_params) + : "r0", "r1", "r2", "r3", "r4", "ip", "lr", "sp" + ); +#else +#error "Unsupported compiler. Use g++ >= 2.8 for OpenBSD/arm." +#endif /* G++ >= 2.8 */ + + return result; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.S new file mode 100644 index 0000000000..69a55b1c1c --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.S @@ -0,0 +1,92 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifdef __APPLE__ +#define SYM(x) _ ## x +#else +#define SYM(x) x +#endif + + .text + .align 2 + .globl SYM(_NS_InvokeByIndex) +#ifndef __APPLE__ + .type _NS_InvokeByIndex,@function +#endif + +/* + * _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + * uint32_t paramCount, nsXPTCVariant* params) + */ + +SYM(_NS_InvokeByIndex): + .cfi_startproc + # set up frame + stp x29, x30, [sp,#-32]! + .cfi_adjust_cfa_offset 32 + .cfi_rel_offset x29, 0 + .cfi_rel_offset x30, 8 + mov x29, sp + .cfi_def_cfa_register x29 + stp x19, x20, [sp,#16] + .cfi_rel_offset x19, 16 + .cfi_rel_offset x20, 24 + + # save methodIndex across function calls + mov w20, w1 + + # end of stack area passed to invoke_copy_to_stack + mov x1, sp + + # assume 8 bytes of stack for each argument with 16-byte alignment + add w19, w2, #1 + and w19, w19, #0xfffffffe + sub sp, sp, w19, uxth #3 + + # temporary place to store args passed in r0-r7,v0-v7 + sub sp, sp, #128 + + # save 'that' on stack + str x0, [sp] + + # start of stack area passed to invoke_copy_to_stack + mov x0, sp + bl SYM(invoke_copy_to_stack) + + # load arguments passed in r0-r7 + ldp x6, x7, [sp, #48] + ldp x4, x5, [sp, #32] + ldp x2, x3, [sp, #16] + ldp x0, x1, [sp],#64 + + # load arguments passed in v0-v7 + ldp d6, d7, [sp, #48] + ldp d4, d5, [sp, #32] + ldp d2, d3, [sp, #16] + ldp d0, d1, [sp],#64 + + # call the method + ldr x16, [x0] + add x16, x16, w20, uxth #3 + ldr x16, [x16] + blr x16 + + add sp, sp, w19, uxth #3 + .cfi_def_cfa_register sp + ldp x19, x20, [sp,#16] + .cfi_restore x19 + .cfi_restore x20 + ldp x29, x30, [sp],#32 + .cfi_adjust_cfa_offset -32 + .cfi_restore x29 + .cfi_restore x30 + ret + .cfi_endproc + +#ifndef __APPLE__ + .size _NS_InvokeByIndex, . - _NS_InvokeByIndex + + .section .note.GNU-stack, "", @progbits +#endif diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s new file mode 100644 index 0000000000..794c4f5c17 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s @@ -0,0 +1,145 @@ + +// Select C numeric constant + .radix C +// for 64 bit mode, use .psr abi64 + .psr abi32 +// big endian + .psr msb +// Section has executable code + .section .text, "ax","progbits" +// procedure named 'NS_InvokeByIndex' + .proc NS_InvokeByIndex +// manual bundling + .explicit + +// extern "C" uint32_t +// invoke_copy_to_stack(uint64_t* d, +// const uint32_t paramCount, nsXPTCVariant* s) + .global invoke_copy_to_stack +// .exclass invoke_copy_to_stack, @fullyvisible + .type invoke_copy_to_stack,@function + +// .exclass NS_InvokeByIndex, @fullyvisible + .type NS_InvokeByIndex,@function + +// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +// uint32_t paramCount, nsXPTCVariant* params); +NS_InvokeByIndex:: + .prologue + .save ar.pfs, r37 +// allocate 4 input args, 6 local args, and 8 output args + alloc r37 = ar.pfs, 4, 6, 8, 0 // M + nop.i 0 ;; // I + +// unwind table already knows gp, no need to specify anything + add r39 = 0, gp // A + .save rp, r36 + mov r36 = rp // I + .vframe r38 + add r38 = 0, sp ;; // A + +// We first calculate the amount of extra memory stack space required +// for the arguments, and register storage. +// We then call invoke_copy_to_stack() to write the argument contents +// to the specified memory regions. +// We then copy the integer arguments to integer registers, and floating +// arguments to float registers. +// Lastly we load the virtual table jump pointer, and call the target +// subroutine. + +// in0 : that +// in1 : methodIndex +// in2 : paramCount +// in3 : params + +// stack frame size is 16 + (8 * even(paramCount)) + 64 + 64 +// 16 byte frame header +// 8 * even(paramCount) memory argument area +// 64 bytes integer register area +// 64 bytes float register area +// This scheme makes sure stack fram size is a multiple of 16 + + .body + add r10 = 8, r0 // A +// r41 points to float register area + add r41 = -64, sp // A +// r40 points to int register area + add r40 = -128, sp ;; // A + + add out1 = 0, r40 // A + add out2 = 0, r41 // A + tbit.z p14,p15 = in2,0 ;; // I + +// compute 8 * even(paramCount) +(p14) shladd r11 = in2, 3, r0 ;; // A +(p15) shladd r11 = in2, 3, r10 ;; // A + sub out0 = r40, r11 ;; // A + +// advance the stack frame + add sp = -16, out0 // A + add out3 = 0, in2 // A + add out4 = 0, in3 // A + +// branch to invoke_copy_to_stack + br.call.sptk.few rp = invoke_copy_to_stack ;; // B + +// restore gp + add gp = 0, r39 // A + add out0 = 0, in0 // A + +// load the integer and float registers + ld8 out1 = [r40], 8 // M + ldfd f8 = [r41], 8 ;; // M + + ld8 out2 = [r40], 8 // M + ldfd f9 = [r41], 8 ;; // M + + ld8 out3 = [r40], 8 // M + ldfd f10 = [r41], 8 ;; // M + + ld8 out4 = [r40], 8 // M + ldfd f11 = [r41], 8 ;; // M + + ld8 out5 = [r40], 8 // M + ldfd f12 = [r41], 8 ;; // M +// 16 * methodIndex + shladd r11 = in1, 4, r0 // A + + ld8 out6 = [r40], 8 // M + ldfd f13 = [r41], 8 ;; // M + + ld8 out7 = [r40], 8 // M + ldfd f14 = [r41], 8 // M + addp4 r8 = 0, in0 ;; // A + +// look up virtual base table and dispatch to target subroutine +// This section assumes 32 bit pointer mode, and virtual base table +// layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html + +// load base table + ld4 r8 = [r8] ;; // M + addp4 r8 = r11, r8 ;; // A + + // first entry is jump pointer, second entry is gp + addp4 r9 = 8, r8 ;; // A +// load jump pointer + ld8 r8 = [r8] + +// load gp + ld8 gp = [r9] ;; // M + mov b6 = r8 ;; // I + +// branch to target virtual function + br.call.sptk.few rp = b6 ;; // B + +// epilog + mov ar.pfs = r37 // I + mov rp = r36 ;; // I + + add sp = 0, r38 // A + add gp = 0, r39 // A + br.ret.sptk.few rp ;; // B + + .endp + + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s new file mode 100644 index 0000000000..3ee7b7971a --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s @@ -0,0 +1,146 @@ + +// Select C numeric constant + .radix C +// for 64 bit mode, use .psr abi64 + .psr abi64 +// little endian + .psr lsb +// Section has executable code + .section .text, "ax","progbits" +// procedure named 'NS_InvokeByIndex' + .proc NS_InvokeByIndex +// manual bundling + .explicit + +// extern "C" uint32_t +// invoke_copy_to_stack(uint64_t* d, +// const uint32_t paramCount, nsXPTCVariant* s) + .global invoke_copy_to_stack +// .exclass invoke_copy_to_stack, @fullyvisible + .type invoke_copy_to_stack,@function + +// .exclass NS_InvokeByIndex, @fullyvisible + .type NS_InvokeByIndex,@function + +// XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +// uint32_t paramCount, nsXPTCVariant* params); +NS_InvokeByIndex:: + .prologue + .save ar.pfs, r37 +// allocate 4 input args, 6 local args, and 8 output args + alloc r37 = ar.pfs, 4, 6, 8, 0 // M + nop.i 0 ;; // I + +// unwind table already knows gp, no need to specify anything + add r39 = 0, gp // A + .save rp, r36 + mov r36 = rp // I + .vframe r38 + add r38 = 0, sp ;; // A + +// We first calculate the amount of extra memory stack space required +// for the arguments, and register storage. +// We then call invoke_copy_to_stack() to write the argument contents +// to the specified memory regions. +// We then copy the integer arguments to integer registers, and floating +// arguments to float registers. +// Lastly we load the virtual table jump pointer, and call the target +// subroutine. + +// in0 : that +// in1 : methodIndex +// in2 : paramCount +// in3 : params + +// stack frame size is 16 + (8 * even(paramCount)) + 64 + 64 +// 16 byte frame header +// 8 * even(paramCount) memory argument area +// 64 bytes integer register area +// 64 bytes float register area +// This scheme makes sure stack fram size is a multiple of 16 + + .body + add r10 = 8, r0 // A +// r41 points to float register area + add r41 = -64, sp // A +// r40 points to int register area + add r40 = -128, sp ;; // A + + add out1 = 0, r40 // A + add out2 = 0, r41 // A + tbit.z p14,p15 = in2,0 ;; // I + +// compute 8 * even(paramCount) +(p14) shladd r11 = in2, 3, r0 ;; // A +(p15) shladd r11 = in2, 3, r10 ;; // A + sub out0 = r40, r11 ;; // A + +// advance the stack frame + add sp = -16, out0 // A + add out3 = 0, in2 // A + add out4 = 0, in3 // A + +// branch to invoke_copy_to_stack + br.call.sptk.few rp = invoke_copy_to_stack ;; // B + +// restore gp + add gp = 0, r39 // A + add out0 = 0, in0 // A + +// load the integer and float registers + ld8 out1 = [r40], 8 // M + ldfd f8 = [r41], 8 ;; // M + + ld8 out2 = [r40], 8 // M + ldfd f9 = [r41], 8 ;; // M + + ld8 out3 = [r40], 8 // M + ldfd f10 = [r41], 8 ;; // M + + ld8 out4 = [r40], 8 // M + ldfd f11 = [r41], 8 ;; // M + + ld8 out5 = [r40], 8 // M + ldfd f12 = [r41], 8 ;; // M +// 16 * methodIndex + shladd r11 = in1, 4, r0 // A + + ld8 out6 = [r40], 8 // M + ldfd f13 = [r41], 8 ;; // M + + ld8 out7 = [r40], 8 // M + ldfd f14 = [r41], 8 // M + add r8 = 0, in0 ;; // A + +// look up virtual base table and dispatch to target subroutine +// This section assumes 64 bit pointer mode, and virtual base table +// layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html + +// load base table + ld8 r8 = [r8] ;; // M + add r8 = r11, r8 ;; // A + + // first entry is jump pointer, second entry is gp + add r9 = 8, r8 ;; // A +// load jump pointer + ld8 r8 = [r8] + +// load gp + ld8 gp = [r9] ;; // M + mov b6 = r8 ;; // I + +// branch to target virtual function + br.call.sptk.few rp = b6 ;; // B + +// epilog + mov ar.pfs = r37 // I + mov rp = r36 ;; // I + + add sp = 0, r38 // A + add gp = 0, r39 // A + br.ret.sptk.few rp ;; // B + + .endp + +/* Magic indicating no need for an executable stack */ + .section .note.GNU-stack, "", @progbits diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_loongarch64.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_loongarch64.S new file mode 100644 index 0000000000..f0a6662986 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_loongarch64.S @@ -0,0 +1,92 @@ +/* This Source Code Form subject to the terms of Mozilla Public + * License, v. 2.0 If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + + .set NGPREGS, 8 + .set NFPREGS, 8 + + .text + .globl _NS_InvokeByIndex + .type _NS_InvokeByIndex, @function +/* + * _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + * uint32_t paramCount, nsXPTCVariant* params) + */ +_NS_InvokeByIndex: + .cfi_startproc + addi.d $sp, $sp, -32 + .cfi_def_cfa_offset 32 + st.d $s0, $sp, 16 + .cfi_offset 23, -16 + st.d $s1, $sp, 8 + .cfi_offset 24, -24 + st.d $s2, $sp, 0 + .cfi_offset 25, -32 + st.d $ra, $sp, 24 + .cfi_offset 1, -8 + + move $s2, $a0 + move $s1, $a1 + move $s0, $sp + .cfi_def_cfa_register 23 + + /* 16-bytes alignment */ + addi.d $a0, $a2, 1 + li.d $t4, 0xfffffffffffffffe + and $a0, $a0, $t4 + slli.d $a0, $a0, 3 + sub.d $sp, $sp, $a0 + move $a4, $sp + + addi.d $sp, $sp, -8*(NFPREGS+NGPREGS) + move $a0, $sp + addi.d $a1, $sp, 8*NGPREGS + + bl invoke_copy_to_stack + + /* 1st argument is this */ + move $a0, $s2 + + ld.d $a1, $sp, 8 + ld.d $a2, $sp, 16 + ld.d $a3, $sp, 24 + ld.d $a4, $sp, 32 + ld.d $a5, $sp, 40 + ld.d $a6, $sp, 48 + ld.d $a7, $sp, 56 + + fld.d $fa0, $sp, 64 + fld.d $fa1, $sp, 72 + fld.d $fa2, $sp, 80 + fld.d $fa3, $sp, 88 + fld.d $fa4, $sp, 96 + fld.d $fa5, $sp, 104 + fld.d $fa6, $sp, 112 + fld.d $fa7, $sp, 120 + + addi.d $sp, $sp, 8*(NGPREGS+NFPREGS) + + ld.d $s2, $s2, 0 + slli.w $s1, $s1, 3 + add.d $s2, $s2, $s1 + ld.d $t3, $s2, 0 + jirl $ra, $t3, 0 + + move $sp, $s0 + .cfi_def_cfa_register 3 + ld.d $s0, $sp, 16 + .cfi_restore 23 + ld.d $s1, $sp, 8 + .cfi_restore 24 + ld.d $s2, $sp, 0 + .cfi_restore 25 + ld.d $ra, $sp, 24 + .cfi_restore 1 + addi.d $sp, $sp, 32 + .cfi_def_cfa_offset -32 + jirl $zero, $ra, 0 + .cfi_endproc + .size _NS_InvokeByIndex, .-_NS_InvokeByIndex + .section .note.GNU-stack, "", @progbits + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S new file mode 100644 index 0000000000..32ff3b3565 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S @@ -0,0 +1,134 @@ +/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * Version: MPL 1.1 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* This code is for MIPS using the O32 ABI. */ + +#ifdef ANDROID +#include <asm/regdef.h> +#include <asm/asm.h> +#include <machine/asm.h> +#else +#include <sys/regdef.h> +#include <sys/asm.h> +#endif + +# NARGSAVE is the argument space in the callers frame, including extra +# 'shadowed' space for the argument registers. The minimum of 4 +# argument slots is sometimes predefined in the header files. +#ifndef NARGSAVE +#define NARGSAVE 4 +#endif + +#define LOCALSZ 3 /* gp, fp, ra */ +#define FRAMESZ ((((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK) + +#define RAOFF (FRAMESZ - (1*SZREG)) +#define FPOFF (FRAMESZ - (2*SZREG)) +#define GPOFF (FRAMESZ - (3*SZREG)) + +#define A0OFF (FRAMESZ + (0*SZREG)) +#define A1OFF (FRAMESZ + (1*SZREG)) +#define A2OFF (FRAMESZ + (2*SZREG)) +#define A3OFF (FRAMESZ + (3*SZREG)) + + .text + +# +# _NS_InvokeByIndex(that, methodIndex, paramCount, params) +# a0 a1 a2 a3 + + .globl _NS_InvokeByIndex + .align 2 + .type _NS_InvokeByIndex,@function + .ent _NS_InvokeByIndex,0 + .frame fp, FRAMESZ, ra +_NS_InvokeByIndex: + SETUP_GP + subu sp, FRAMESZ + + # specify the save register mask for gp, fp, ra, a3 - a0 + .mask 0xD00000F0, RAOFF-FRAMESZ + + sw ra, RAOFF(sp) + sw fp, FPOFF(sp) + + # we can't use .cprestore in a variable stack frame + sw gp, GPOFF(sp) + + sw a0, A0OFF(sp) + sw a1, A1OFF(sp) + sw a2, A2OFF(sp) + sw a3, A3OFF(sp) + + # save bottom of fixed frame + move fp, sp + + # extern "C" uint32 + # invoke_count_words(uint32_t paramCount, nsXPTCVariant* s); + la t9, invoke_count_words + move a0, a2 + move a1, a3 + jalr t9 + lw gp, GPOFF(fp) + + # allocate variable stack, with a size of: + # wordsize (of 4 bytes) * result (already aligned to dword) + # but a minimum of 16 byte + sll v0, 2 + slt t0, v0, 16 + beqz t0, 1f + li v0, 16 +1: subu sp, v0 + + # let a0 point to the bottom of the variable stack, allocate + # another fixed stack for: + # extern "C" void + # invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, + # nsXPTCVariant* s); + la t9, invoke_copy_to_stack + move a0, sp + lw a1, A2OFF(fp) + lw a2, A3OFF(fp) + subu sp, 16 + jalr t9 + lw gp, GPOFF(fp) + + # back to the variable stack frame + addu sp, 16 + + # calculate the function we need to jump to, which must then be + # stored in t9 + lw a0, A0OFF(fp) # a0 = set "that" to be "this" + lw t0, A1OFF(fp) # a1 = methodIndex + lw t9, 0(a0) + # t0 = methodIndex << PTRLOG + sll t0, t0, PTRLOG + addu t9, t0 + lw t9, (t9) + + # Set a1-a3 to what invoke_copy_to_stack told us. a0 is already + # the "this" pointer. We don't have to care about floating + # point arguments, the non-FP "this" pointer as first argument + # means they'll never be used. + lw a1, 1*SZREG(sp) + lw a2, 2*SZREG(sp) + lw a3, 3*SZREG(sp) + + jalr t9 + # Micro-optimization: There's no gp usage below this point, so + # we don't reload. + # lw gp, GPOFF(fp) + + # leave variable stack frame + move sp, fp + + lw ra, RAOFF(sp) + lw fp, FPOFF(sp) + + addiu sp, FRAMESZ + j ra +END(_NS_InvokeByIndex) diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S new file mode 100644 index 0000000000..d2c5595ab4 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S @@ -0,0 +1,121 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <sys/regdef.h> +#include <sys/asm.h> + +.text +.globl invoke_count_words +.globl invoke_copy_to_stack + +LOCALSZ=7 # a0, a1, a2, a3, s0, ra, gp +FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK + +RAOFF=FRAMESZ-(1*SZREG) +A0OFF=FRAMESZ-(2*SZREG) +A1OFF=FRAMESZ-(3*SZREG) +A2OFF=FRAMESZ-(4*SZREG) +A3OFF=FRAMESZ-(5*SZREG) +S0OFF=FRAMESZ-(6*SZREG) +GPOFF=FRAMESZ-(7*SZREG) + +# +# _NS_InvokeByIndex(that, methodIndex, paramCount, params) +# a0 a1 a2 a3 + +NESTED(_NS_InvokeByIndex, FRAMESZ, ra) + PTR_SUBU sp, FRAMESZ + SETUP_GP64(GPOFF, _NS_InvokeByIndex) + + REG_S ra, RAOFF(sp) + REG_S a0, A0OFF(sp) + REG_S a1, A1OFF(sp) + REG_S a2, A2OFF(sp) + REG_S a3, A3OFF(sp) + REG_S s0, S0OFF(sp) + + # invoke_count_words(paramCount, params) + move a0, a2 + move a1, a3 + jal invoke_count_words + + # invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, + # nsXPTCVariant* s, uint32_t *reg) + + REG_L a1, A2OFF(sp) # a1 - paramCount + REG_L a2, A3OFF(sp) # a2 - params + + # save sp before we copy the params to the stack + move t0, sp + + # assume full size of 16 bytes per param to be safe + sll v0, 4 # 16 bytes * num params + PTR_SUBU sp, sp, v0 # make room + move a0, sp # a0 - param stack address + + # create temporary stack space to write int and fp regs + PTR_SUBU sp, 64 # 64 = 8 regs of 8 bytes + move a3, sp + + # save the old sp and save the arg stack + PTR_SUBU sp, sp, 16 + REG_S t0, 0(sp) + REG_S a0, 8(sp) + + # copy the param into the stack areas + jal invoke_copy_to_stack + + REG_L t3, 8(sp) # get previous a0 + REG_L s0, 0(sp) # get orig sp back and save away our stack pointer + + REG_L a0, A0OFF(s0) # a0 - that + REG_L a1, A1OFF(s0) # a1 - methodIndex + + # t1 = methodIndex * pow(2, PTRLOG) + # (use shift instead of mult) + sll t1, a1, PTRLOG + + # calculate the function we need to jump to, + # which must then be saved in t9 + PTR_L t9, 0(a0) + PTR_ADDU t9, t9, t1 + PTR_L t9, (t9) + + # get register save area from invoke_copy_to_stack + PTR_SUBU t1, t3, 64 + + # a1..a7 and f13..f19 should now be set to what + # invoke_copy_to_stack told us. skip a0 and f12 + # because that's the "this" pointer + + REG_L a1, 0(t1) + REG_L a2, 8(t1) + REG_L a3, 16(t1) + REG_L a4, 24(t1) + REG_L a5, 32(t1) + REG_L a6, 40(t1) + REG_L a7, 48(t1) + + l.d $f13, 0(t1) + l.d $f14, 8(t1) + l.d $f15, 16(t1) + l.d $f16, 24(t1) + l.d $f17, 32(t1) + l.d $f18, 40(t1) + l.d $f19, 48(t1) + + # create the stack pointer for the function + move sp, t3 + + jalr t9 + + ## restore stack pointer. + move sp, s0 + + RESTORE_GP64 + REG_L ra, RAOFF(sp) + REG_L s0, S0OFF(sp) + PTR_ADDU sp, FRAMESZ + j ra +.end _NS_InvokeByIndex diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s new file mode 100644 index 0000000000..6fa9a86ba8 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s @@ -0,0 +1,131 @@ + .LEVEL 1.1 +framesz .EQU 128 + +; XPTC_InvokeByIndex(nsISuppots* that, uint32_t methodIndex, +; uint32_t paramCount, nsXPTCVariant* params); + +; g++ need to compile everything with -fvtable-thunks ! + + .SPACE $TEXT$,SORT=8 + .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24 +XPTC_InvokeByIndex + .PROC + .CALLINFO CALLER,FRAME=72,ENTRY_GR=%r3,SAVE_RP,SAVE_SP,ARGS_SAVED,ALLOCA_FRAME + + ; frame marker takes 48 bytes, + ; register spill area takes 8 bytes, + ; local stack area takes 72 bytes result in 128 bytes total + + .ENTRY + STW %rp,-20(%sp) + STW,MA %r3,128(%sp) + + LDO -framesz(%r30),%r28 + STW %r28,-4(%r30) ; save previous sp + STW %r19,-32(%r30) + + STW %r26,-36-framesz(%r30) ; save argument registers in + STW %r25,-40-framesz(%r30) ; in PREVIOUS frame + STW %r24,-44-framesz(%r30) ; + STW %r23,-48-framesz(%r30) ; + + B,L .+8,%r2 + ADDIL L'invoke_count_bytes-$PIC_pcrel$1+4,%r2,%r1 + LDO R'invoke_count_bytes-$PIC_pcrel$2+8(%r1),%r1 +$PIC_pcrel$1 + LDSID (%r1),%r31 +$PIC_pcrel$2 + MTSP %r31,%sr0 + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26;out=28 + BE,L 0(%sr0,%r1),%r31 + COPY %r31,%r2 + + CMPIB,>= 0,%r28, .+76 + COPY %r30,%r3 ; copy stack ptr to saved stack ptr + ADD %r30,%r28,%r30 ; extend stack frame + LDW -4(%r3),%r28 ; move frame + STW %r28,-4(%r30) + LDW -8(%r3),%r28 + STW %r28,-8(%r30) + LDW -12(%r3),%r28 + STW %r28,-12(%r30) + LDW -16(%r3),%r28 + STW %r28,-16(%r30) + LDW -20(%r3),%r28 + STW %r28,-20(%r30) + LDW -24(%r3),%r28 + STW %r28,-24(%r30) + LDW -28(%r3),%r28 + STW %r28,-28(%r30) + LDW -32(%r3),%r28 + STW %r28,-32(%r30) + + LDO -40(%r30),%r26 ; load copy address + LDW -44-framesz(%r3),%r25 ; load rest of 2 arguments + LDW -48-framesz(%r3),%r24 ; + + LDW -32(%r30),%r19 ; shared lib call destroys r19; reload + B,L .+8,%r2 + ADDIL L'invoke_copy_to_stack-$PIC_pcrel$3+4,%r2,%r1 + LDO R'invoke_copy_to_stack-$PIC_pcrel$4+8(%r1),%r1 +$PIC_pcrel$3 + LDSID (%r1),%r31 +$PIC_pcrel$4 + MTSP %r31,%sr0 + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26 + BE,L 0(%sr0,%r1),%r31 + COPY %r31,%r2 + + LDO -48(%r30),%r20 + EXTRW,U,= %r28,31,1,%r22 + FLDD 0(%r20),%fr7 ; load double arg 1 + EXTRW,U,= %r28,30,1,%r22 + FLDW 8(%r20),%fr5L ; load float arg 1 + EXTRW,U,= %r28,29,1,%r22 + FLDW 4(%r20),%fr6L ; load float arg 2 + EXTRW,U,= %r28,28,1,%r22 + FLDW 0(%r20),%fr7L ; load float arg 3 + + LDW -36-framesz(%r3),%r26 ; load ptr to 'that' + LDW -40(%r30),%r25 ; load the rest of dispatch argument registers + LDW -44(%r30),%r24 + LDW -48(%r30),%r23 + + LDW -36-framesz(%r3),%r20 ; load vtable addr + LDW -40-framesz(%r3),%r28 ; load index + LDW 0(%r20),%r20 ; follow vtable + LDO 16(%r20),%r20 ; offset vtable by 16 bytes (g++: 8, aCC: 16) + SH2ADDL %r28,%r20,%r28 ; add 4*index to vtable entry + LDW 0(%r28),%r22 ; load vtable entry + + B,L .+8,%r2 + ADDIL L'$$dyncall_external-$PIC_pcrel$5+4,%r2,%r1 + LDO R'$$dyncall_external-$PIC_pcrel$6+8(%r1),%r1 +$PIC_pcrel$5 + LDSID (%r1),%r31 +$PIC_pcrel$6 + MTSP %r31,%sr0 + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR +;in=22-26;out=28; + BE,L 0(%sr0,%r1),%r31 + COPY %r31,%r2 + + LDW -32(%r30),%r19 + COPY %r3,%r30 ; restore saved stack ptr + + LDW -148(%sp),%rp + BVE (%rp) + .EXIT + LDW,MB -128(%sp),%r3 + + .PROCEND ;in=23,24,25,26; + + .ALIGN 8 + .SPACE $TEXT$ + .SUBSPA $CODE$ + .IMPORT $$dyncall_external,MILLICODE + .IMPORT invoke_count_bytes,CODE + .IMPORT invoke_copy_to_stack,CODE + .EXPORT XPTC_InvokeByIndex,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR,LONG_RETURN + .END + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s new file mode 100644 index 0000000000..7a207addfd --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s @@ -0,0 +1,108 @@ +/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * Version: MPL 1.1 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .LEVEL 1.1 + .text + .align 4 + +framesz: + .equ 128 + +.globl NS_InvokeByIndex + .type NS_InvokeByIndex, @function + + +NS_InvokeByIndex: + .PROC + .CALLINFO FRAME=72, CALLER,SAVE_RP, SAVE_SP, ENTRY_GR=3 + .ENTRY + +; frame marker takes 48 bytes, +; register spill area takes 8 bytes, +; local stack area takes 72 bytes result in 128 bytes total + + STW %rp,-20(%sp) + STW,MA %r3,128(%sp) + + LDO -framesz(%r30),%r28 + STW %r28,-4(%r30) ; save previous sp + STW %r19,-32(%r30) + + STW %r26,-36-framesz(%r30) ; save argument registers in + STW %r25,-40-framesz(%r30) ; in PREVIOUS frame + STW %r24,-44-framesz(%r30) ; + STW %r23,-48-framesz(%r30) ; + + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26;out=28 + BL invoke_count_bytes,%r31 + COPY %r31,%r2 + + CMPIB,>= 0,%r28, .+76 + COPY %r30,%r3 ; copy stack ptr to saved stack ptr + ADD %r30,%r28,%r30 ; extend stack frame + LDW -4(%r3),%r28 ; move frame + STW %r28,-4(%r30) + LDW -8(%r3),%r28 + STW %r28,-8(%r30) + LDW -12(%r3),%r28 + STW %r28,-12(%r30) + LDW -16(%r3),%r28 + STW %r28,-16(%r30) + LDW -20(%r3),%r28 + STW %r28,-20(%r30) + LDW -24(%r3),%r28 + STW %r28,-24(%r30) + LDW -28(%r3),%r28 + STW %r28,-28(%r30) + LDW -32(%r3),%r28 + STW %r28,-32(%r30) + + LDO -40(%r30),%r26 ; load copy address + LDW -44-framesz(%r3),%r25 ; load rest of 2 arguments + LDW -48-framesz(%r3),%r24 ; + + LDW -32(%r30),%r19 ; shared lib call destroys r19; reload + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26 + BL invoke_copy_to_stack,%r31 + COPY %r31,%r2 + + LDO -48(%r30),%r20 + EXTRW,U,= %r28,31,1,%r22 + FLDD 0(%r20),%fr7 ; load double arg 1 + EXTRW,U,= %r28,30,1,%r22 + FLDW 8(%r20),%fr5L ; load float arg 1 + EXTRW,U,= %r28,29,1,%r22 + FLDW 4(%r20),%fr6L ; load float arg 2 + EXTRW,U,= %r28,28,1,%r22 + FLDW 0(%r20),%fr7L ; load float arg 3 + + LDW -36-framesz(%r3),%r26 ; load ptr to 'that' + LDW -40(%r30),%r25 ; load the rest of dispatch argument registers + LDW -44(%r30),%r24 + LDW -48(%r30),%r23 + + LDW -36-framesz(%r3),%r20 ; load vtable addr + LDW -40-framesz(%r3),%r28 ; load index + LDW 0(%r20),%r20 ; follow vtable + SH2ADDL %r28,%r20,%r28 ; add 4*index to vtable entry + LDW 0(%r28),%r22 ; load vtable entry + + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR ;in=22-26;out=28; + BL $$dyncall,%r31 + COPY %r31,%r2 + + LDW -32(%r30),%r19 + COPY %r3,%r30 ; restore saved stack ptr + + LDW -148(%sp),%rp + LDWM -128(%sp),%r3 + BV,N (%rp) + NOP + .EXIT + .PROCEND ;in=23,24,25,26; + .SIZE NS_InvokeByIndex, .-NS_InvokeByIndex + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S new file mode 100644 index 0000000000..d2cab6c813 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S @@ -0,0 +1,167 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set r1,1; .set r2,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + +# The ABI defines a fixed stack frame area of 4 doublewords (ELFv2) +# or 6 doublewords (ELFv1); the last of these doublewords is used +# as TOC pointer save area. The fixed area is followed by a parameter +# save area of 8 doublewords (used for vararg routines), followed +# by space for parameters passed on the stack. +# +# We set STACK_TOC to the offset of the TOC pointer save area, and +# STACK_PARAMS to the offset of the first on-stack parameter. + +#if _CALL_ELF == 2 +#define STACK_TOC 24 +#define STACK_PARAMS 96 +#else +#define STACK_TOC 40 +#define STACK_PARAMS 112 +#endif + +# +# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +# uint32_t paramCount, nsXPTCVariant* params) +# + +#if _CALL_ELF == 2 + .section ".text" + .type NS_InvokeByIndex,@function + .globl NS_InvokeByIndex + .align 2 +NS_InvokeByIndex: +0: addis 2,12,(.TOC.-0b)@ha + addi 2,2,(.TOC.-0b)@l + .localentry NS_InvokeByIndex,.-NS_InvokeByIndex +#else + .section ".toc","aw" + .section ".text" + .align 2 + .globl NS_InvokeByIndex + .section ".opd","aw" + .align 3 +NS_InvokeByIndex: + .quad .NS_InvokeByIndex,.TOC.@tocbase + .previous + .type NS_InvokeByIndex,@function +.NS_InvokeByIndex: +#endif + mflr 0 + std 0,16(r1) + + std r29,-24(r1) + std r30,-16(r1) + std r31,-8(r1) + + mr r29,r3 # Save 'that' in r29 + mr r30,r4 # Save 'methodIndex' in r30 + mr r31,r1 # Save old frame + + # Allocate stack frame with space for params. Since at least the + # first 7 parameters (not including 'that') will be in registers, + # we don't actually need stack space for those. We must ensure + # that the stack remains 16-byte aligned. + # + # | (fixed area + | | 7 GP | 13 FP | 3 NV | + # | param. save) |(params)........| regs | regs | regs | + # (r1)......(+STACK_PARAMS)... (-23*8).(-16*8).(-3*8)..(r31) + + # +stack frame, -unused stack params, +regs storage, +1 for alignment + addi r7,r5,((STACK_PARAMS/8)-7+7+13+3+1) + rldicr r7,r7,3,59 # multiply by 8 and mask with ~15 + neg r7,r7 + stdux r1,r1,r7 + + + # Call invoke_copy_to_stack(uint64_t* gpregs, double* fpregs, + # uint32_t paramCount, nsXPTCVariant* s, + # uint64_t* d)) + + # r5, r6 are passed through intact (paramCount, params) + # r7 (d) has to be r1+STACK_PARAMS + # -- where parameters are passed on the stack. + # r3, r4 are above that, easier to address from r31 than from r1 + + subi r3,r31,(23*8) # r3 --> GPRS + subi r4,r31,(16*8) # r4 --> FPRS + addi r7,r1,STACK_PARAMS # r7 --> params + bl invoke_copy_to_stack + nop + + # Set up to invoke function + + ld r9,0(r29) # vtable (r29 is 'that') + mr r3,r29 # self is first arg, obviously + + sldi r30,r30,3 # Find function descriptor + add r9,r9,r30 + ld r12,0(r9) + + std r2,STACK_TOC(r1) # Save r2 (TOC pointer) + +#if _CALL_ELF == 2 + mtctr r12 +#else + ld r0,0(r12) # Actual address from fd. + mtctr 0 + ld r11,16(r12) # Environment pointer from fd. + ld r2,8(r12) # TOC pointer from fd. +#endif + + # Load FP and GP registers as required + ld r4, -(23*8)(r31) + ld r5, -(22*8)(r31) + ld r6, -(21*8)(r31) + ld r7, -(20*8)(r31) + ld r8, -(19*8)(r31) + ld r9, -(18*8)(r31) + ld r10, -(17*8)(r31) + + lfd f1, -(16*8)(r31) + lfd f2, -(15*8)(r31) + lfd f3, -(14*8)(r31) + lfd f4, -(13*8)(r31) + lfd f5, -(12*8)(r31) + lfd f6, -(11*8)(r31) + lfd f7, -(10*8)(r31) + lfd f8, -(9*8)(r31) + lfd f9, -(8*8)(r31) + lfd f10, -(7*8)(r31) + lfd f11, -(6*8)(r31) + lfd f12, -(5*8)(r31) + lfd f13, -(4*8)(r31) + + bctrl # Do it + + ld r2,STACK_TOC(r1) # Load our own TOC pointer + ld r1,0(r1) # Revert stack frame + ld 0,16(r1) # Reload lr + mtlr 0 + ld 29,-24(r1) # Restore NVGPRS + ld 30,-16(r1) + ld 31,-8(r1) + blr + +#if _CALL_ELF == 2 + .size NS_InvokeByIndex,.-NS_InvokeByIndex +#else + .size NS_InvokeByIndex,.-.NS_InvokeByIndex +#endif + + # Magic indicating no need for an executable stack + .section .note.GNU-stack, "", @progbits diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s new file mode 100644 index 0000000000..eb6b6661d3 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s @@ -0,0 +1,129 @@ +# +# -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 +.set BO_IF,12 +.set CR0_EQ,2 + + + + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex" + + +# .text section + + .csect H.10.NO_SYMBOL{PR} + .globl .NS_InvokeByIndex + .globl NS_InvokeByIndex{DS} + .extern .invoke_copy_to_stack + .extern ._ptrgl{PR} + + +# +# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +# uint32_t paramCount, nsXPTCVariant* params) +# + +.NS_InvokeByIndex: + mflr r0 + stw r31,-4(sp) +# +# save off the incoming values in the caller's parameter area +# + stw r3,24(sp) # that + stw r4,28(sp) # methodIndex + stw r5,32(sp) # paramCount + stw r6,36(sp) # params + stw r0,8(sp) + stwu sp,-136(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers + +# prepare args for 'invoke_copy_to_stack' call +# + lwz r4,168(sp) # paramCount + lwz r5,172(sp) # params + mr r6,sp # fprData + slwi r3,r4,3 # number of bytes of stack required + # at most 8*paramCount + addi r3,r3,28 # linkage area + mr r31,sp # save original stack top + subfc sp,r3,sp # bump the stack + addi r3,sp,28 # parameter pointer excludes linkage area size + 'this' + + bl .invoke_copy_to_stack + nop + + lfd f1,0(r31) # Restore floating point registers + lfd f2,8(r31) + lfd f3,16(r31) + lfd f4,24(r31) + lfd f5,32(r31) + lfd f6,40(r31) + lfd f7,48(r31) + lfd f8,56(r31) + lfd f9,64(r31) + lfd f10,72(r31) + lfd f11,80(r31) + lfd f12,88(r31) + lfd f13,96(r31) + + lwz r3,160(r31) # that + lwz r4,0(r3) # get vTable from 'that' + lwz r5,164(r31) # methodIndex + slwi r5,r5,3 # methodIndex * 8 + addi r5,r5,8 # step over junk at start of vTable ! + lwzx r11,r5,r4 # get function pointer + + addi r5,r5,4 # We need to manually adjust the 'that' pointer, this is CFRONT based + lwzx r5,r4,r5 # offset = r4(vtable) + r5(methodIndex offset) - 4 + add r3,r5,r3 # adjust 'that' r3 = r3 + r5 + + lwz r4,28(sp) + lwz r5,32(sp) + lwz r6,36(sp) + lwz r7,40(sp) + lwz r8,44(sp) + lwz r9,48(sp) + lwz r10,52(sp) + + bl ._ptrgl{PR} + nop + + mr sp,r31 + lwz r0,144(sp) + addi sp,sp,136 + mtlr r0 + lwz r31,-4(sp) + blr + + +# .data section + + .toc # 0x00000038 +T.18.NS_InvokeByIndex: + .tc H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS} + + .csect NS_InvokeByIndex{DS} + .long .NS_InvokeByIndex # "\0\0\0\0" + .long TOC{TC0} # "\0\0\0008" + .long 0x00000000 # "\0\0\0\0" +# End csect NS_InvokeByIndex{DS} + +# .bss section diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s new file mode 100644 index 0000000000..722583de5b --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s @@ -0,0 +1,128 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 +.set BO_IF,12 +.set CR0_EQ,2 + + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex" + + +# .text section + + .csect H.10.NO_SYMBOL{PR} + .globl .NS_InvokeByIndex + .globl NS_InvokeByIndex{DS} + .extern .invoke_copy_to_stack + .extern ._ptrgl{PR} + +# +# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +# uint32_t paramCount, nsXPTCVariant* params) +# + +.NS_InvokeByIndex: + mflr r0 + std r31,-8(sp) +# +# save off the incoming values in the caller's parameter area +# + std r3,48(sp) # that + std r4,56(sp) # methodIndex + std r5,64(sp) # paramCount + std r6,72(sp) # params + std r0,16(sp) + stdu sp,-168(sp) # 2*24=48 for linkage area, + # 8*13=104 for fprData area + # 16 for saved registers + +# prepare args for 'invoke_copy_to_stack' call +# + ld r4,232(sp) # paramCount (168+8+56) + ld r5,240(sp) # params + mr r6,sp # fprData + sldi r3,r4,3 # number of bytes of stack required + # is at most numParams*8 + addi r3,r3,56 # linkage area (48) + this (8) + mr r31,sp # save original stack top + subfc sp,r3,sp # bump the stack + addi r3,sp,56 # parameter pointer excludes linkage area + # size + 'this' + + bl .invoke_copy_to_stack + nop + + lfd f1,0(r31) # Restore floating point registers + lfd f2,8(r31) + lfd f3,16(r31) + lfd f4,24(r31) + lfd f5,32(r31) + lfd f6,40(r31) + lfd f7,48(r31) + lfd f8,56(r31) + lfd f9,64(r31) + lfd f10,72(r31) + lfd f11,80(r31) + lfd f12,88(r31) + lfd f13,96(r31) + + ld r3,216(r31) # that (168+48) + ld r4,0(r3) # get vTable from 'that' + ld r5,224(r31) # methodIndex (168+56) + sldi r5,r5,3 # methodIndex * 8 + # No junk at the start of 64bit vtable !!! + ldx r11,r5,r4 # get function pointer (this jumps + # either to the function if no adjustment + # is needed (displacement = 0), or it + # jumps to the thunk code, which will jump + # to the function at the end) + + # No adjustment of the that pointer in 64bit mode, this is done + # by the thunk code + + ld r4,56(sp) + ld r5,64(sp) + ld r6,72(sp) + ld r7,80(sp) + ld r8,88(sp) + ld r9,96(sp) + ld r10,104(sp) + + bl ._ptrgl{PR} + nop + + mr sp,r31 + ld r0,184(sp) # 168+16 + addi sp,sp,168 + mtlr r0 + ld r31,-8(sp) + blr + +# .data section + + .toc # 0x00000038 +T.18.NS_InvokeByIndex: + .tc H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS} + + .csect NS_InvokeByIndex{DS} + .llong .NS_InvokeByIndex # "\0\0\0\0" + .llong TOC{TC0} # "\0\0\0008" + .llong 0x00000000 # "\0\0\0\0" +# End csect NS_InvokeByIndex{DS} + +# .bss section diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s new file mode 100644 index 0000000000..414a6536fa --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s @@ -0,0 +1,124 @@ +# +# -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 +.set BO_IF,12 +.set CR0_EQ,2 + + + + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex" + + +# .text section + + .csect H.10.NO_SYMBOL{PR} + .globl .NS_InvokeByIndex + .globl NS_InvokeByIndex{DS} + .extern .invoke_copy_to_stack + .extern ._ptrgl{PR} + + +# +# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +# uint32_t paramCount, nsXPTCVariant* params) +# + +.NS_InvokeByIndex: + mflr r0 + stw r31,-4(sp) +# +# save off the incoming values in the caller's parameter area +# + stw r3,24(sp) # that + stw r4,28(sp) # methodIndex + stw r5,32(sp) # paramCount + stw r6,36(sp) # params + stw r0,8(sp) + stwu sp,-136(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers + +# prepare args for 'invoke_copy_to_stack' call +# + lwz r4,168(sp) # paramCount + lwz r5,172(sp) # params + mr r6,sp # fprData + slwi r3,r4,3 # number of bytes of stack required + # at most 8*paramCount + addi r3,r3,28 # linkage area + mr r31,sp # save original stack top + subfc sp,r3,sp # bump the stack + addi r3,sp,28 # parameter pointer excludes linkage area size + 'this' + + bl .invoke_copy_to_stack + nop + + lfd f1,0(r31) # Restore floating point registers + lfd f2,8(r31) + lfd f3,16(r31) + lfd f4,24(r31) + lfd f5,32(r31) + lfd f6,40(r31) + lfd f7,48(r31) + lfd f8,56(r31) + lfd f9,64(r31) + lfd f10,72(r31) + lfd f11,80(r31) + lfd f12,88(r31) + lfd f13,96(r31) + + lwz r3,160(r31) # that + lwz r4,0(r3) # get vTable from 'that' + lwz r5,164(r31) # methodIndex + slwi r5,r5,2 # methodIndex * 4 + lwzx r11,r5,r4 # get function pointer + + lwz r4,28(sp) + lwz r5,32(sp) + lwz r6,36(sp) + lwz r7,40(sp) + lwz r8,44(sp) + lwz r9,48(sp) + lwz r10,52(sp) + + bl ._ptrgl{PR} + nop + + mr sp,r31 + lwz r0,144(sp) + addi sp,sp,136 + mtlr r0 + lwz r31,-4(sp) + blr + + +# .data section + + .toc # 0x00000038 +T.18.NS_InvokeByIndex: + .tc H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS} + + .csect NS_InvokeByIndex{DS} + .long .NS_InvokeByIndex # "\0\0\0\0" + .long TOC{TC0} # "\0\0\0008" + .long 0x00000000 # "\0\0\0\0" +# End csect NS_InvokeByIndex{DS} + +# .bss section diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S new file mode 100644 index 0000000000..619e428a9c --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S @@ -0,0 +1,98 @@ +// -*- Mode: Asm -*- +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + + .section ".text" + .align 2 + .globl NS_InvokeByIndex + .type NS_InvokeByIndex,@function + +// +// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +// uint32_t paramCount, nsXPTCVariant* params) +// + +NS_InvokeByIndex: + stwu sp,-32(sp) // setup standard stack frame + mflr r0 // save LR + stw r3,8(sp) // r3 <= that + stw r4,12(sp) // r4 <= methodIndex + stw r30,16(sp) + stw r31,20(sp) + + stw r0,36(sp) // store LR backchain + mr r31,sp + + rlwinm r10,r5,3,0,27 // r10 = (ParamCount * 2 * 4) & ~0x0f + addi r0,r10,96 // reserve stack for GPR and FPR register save area r0 = r10 + 96 + lwz r9,0(sp) // r9 = backchain + neg r0,r0 + stwux r9,sp,r0 // reserve stack space and save SP backchain + + addi r3,sp,8 // r3 <= args + mr r4,r5 // r4 <= paramCount + mr r5,r6 // r5 <= params + add r6,r3,r10 // r6 <= gpregs ( == args + r10 ) + mr r30,r6 // store in r30 for use later... +#ifndef __NO_FPRS__ + addi r7,r6,32 // r7 <= fpregs ( == gpregs + 32 ) +#else + li r7, 0 +#endif + + bl invoke_copy_to_stack@local // (args, paramCount, params, gpregs, fpregs) +#ifndef __NO_FPRS__ + lfd f1,32(r30) // load FP registers with method parameters + lfd f2,40(r30) + lfd f3,48(r30) + lfd f4,56(r30) + lfd f5,64(r30) + lfd f6,72(r30) + lfd f7,80(r30) + lfd f8,88(r30) +#endif + lwz r3,8(r31) // r3 <= that + lwz r4,12(r31) // r4 <= methodIndex + lwz r5,0(r3) // r5 <= vtable ( == *that ) + slwi r4,r4,2 // convert to offset ( *= 4 ) + lwzx r0,r5,r4 // r0 <= methodpointer ( == vtable + offset ) + + lwz r4,4(r30) // load GP regs with method parameters + lwz r5,8(r30) + lwz r6,12(r30) + lwz r7,16(r30) + lwz r8,20(r30) + lwz r9,24(r30) + lwz r10,28(r30) + + mtlr r0 // copy methodpointer to LR + blrl // call method + + lwz r30,16(r31) // restore r30 & r31 + lwz r31,20(r31) + + lwz r11,0(sp) // clean up the stack + lwz r0,4(r11) + mtlr r0 + mr sp,r11 + blr + + /* Magic indicating no need for an executable stack */ + .section .note.GNU-stack, "", @progbits diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S new file mode 100644 index 0000000000..2f8dc73b2e --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S @@ -0,0 +1,94 @@ +// -*- Mode: Asm -*- +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + + .section ".text" + .align 2 + .globl NS_InvokeByIndex + .type NS_InvokeByIndex,@function + +// +// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +// uint32_t paramCount, nsXPTCVariant* params) +// + +NS_InvokeByIndex: + stwu sp,-32(sp) // setup standard stack frame + mflr r0 // save LR + stw r3,8(sp) // r3 <= that + stw r4,12(sp) // r4 <= methodIndex + stw r30,16(sp) + stw r31,20(sp) + + stw r0,36(sp) // store LR backchain + mr r31,sp + + rlwinm r10,r5,3,0,27 // r10 = (ParamCount * 2 * 4) & ~0x0f + addi r0,r10,96 // reserve stack for GPR and FPR register save area r0 = r10 + 96 + lwz r9,0(sp) // r9 = backchain + neg r0,r0 + stwux r9,sp,r0 // reserve stack space and save SP backchain + + addi r3,sp,8 // r3 <= args + mr r4,r5 // r4 <= paramCount + mr r5,r6 // r5 <= params + add r6,r3,r10 // r6 <= gpregs ( == args + r10 ) + mr r30,r6 // store in r30 for use later... + addi r7,r6,32 // r7 <= fpregs ( == gpregs + 32 ) + + bl invoke_copy_to_stack@local // (args, paramCount, params, gpregs, fpregs) + + lfd f1,32(r30) // load FP registers with method parameters + lfd f2,40(r30) + lfd f3,48(r30) + lfd f4,56(r30) + lfd f5,64(r30) + lfd f6,72(r30) + lfd f7,80(r30) + lfd f8,88(r30) + + lwz r3,8(r31) // r3 <= that + lwz r4,12(r31) // r4 <= methodIndex + lwz r5,0(r3) // r5 <= vtable ( == *that ) + slwi r4,r4,2 // convert to offset ( *= 4 ) + lwzx r0,r5,r4 // r0 <= methodpointer ( == vtable + offset ) + + lwz r4,4(r30) // load GP regs with method parameters + lwz r5,8(r30) + lwz r6,12(r30) + lwz r7,16(r30) + lwz r8,20(r30) + lwz r9,24(r30) + lwz r10,28(r30) + + mtlr r0 // copy methodpointer to LR + blrl // call method + + lwz r30,16(r31) // restore r30 & r31 + lwz r31,20(r31) + + lwz r11,0(sp) // clean up the stack + lwz r0,4(r11) + mtlr r0 + mr sp,r11 + blr + + // Magic indicating no need for an executable stack + .section .note.GNU-stack, "", @progbits diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s new file mode 100644 index 0000000000..1dc12b2b30 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s @@ -0,0 +1,142 @@ +# +# -*- Mode: Asm -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# +# ** Assumed vtable layout (obtained by disassembling with gdb): +# ** 4 bytes per vtable entry, skip 0th and 1st entries, so the mapping +# ** from index to entry is (4 * index) + 8. +# + +.text + .align 2 +# +# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +# uint32_t paramCount, nsXPTCVariant* params) +# + +.globl __NS_InvokeByIndex +__NS_InvokeByIndex: + mflr r0 + stw r31,-4(r1) +# +# save off the incoming values in the callers parameter area +# + stw r3,24(r1) ; that + stw r4,28(r1) ; methodIndex + stw r5,32(r1) ; paramCount + stw r6,36(r1) ; params + stw r0,8(r1) + stwu r1,-144(r1) ; 24 for linkage area, + ; 8*13 for fprData area, + ; 8 for saved registers, + ; 8 to keep stack 16-byte aligned + +# set up for and call 'invoke_count_words' to get new stack size +# + mr r3,r5 + mr r4,r6 + + stwu r1,-24(r1) + bl L_invoke_count_words$stub + lwz r1,0(r1) + +# prepare args for 'invoke_copy_to_stack' call +# + lwz r4,176(r1) ; paramCount + lwz r5,180(r1) ; params + mr r6,r1 ; fprData + slwi r3,r3,2 ; number of stack bytes required + addi r3,r3,28 ; linkage area + mr r31,r1 ; save original stack top + sub r1,r1,r3 ; bump the stack + clrrwi r1,r1,4 ; keep the stack 16-byte aligned + addi r3,r31,144 ; act like real alloca, so 0(sp) always + stw r3,0(r1) ; points back to previous stack frame + addi r3,r1,28 ; parameter pointer excludes linkage area size + 'this' + +# create "temporary" stack frame for _invoke_copy_to_stack to operate in. + stwu r1,-40(r1) + bl L_invoke_copy_to_stack$stub +# remove temporary stack frame. + lwz r1,0(r1) + + lfd f1,0(r31) + lfd f2,8(r31) + lfd f3,16(r31) + lfd f4,24(r31) + lfd f5,32(r31) + lfd f6,40(r31) + lfd f7,48(r31) + lfd f8,56(r31) + lfd f9,64(r31) + lfd f10,72(r31) + lfd f11,80(r31) + lfd f12,88(r31) + lfd f13,96(r31) + + lwz r3,168(r31) ; that + lwz r4,0(r3) ; get vTable from 'that' + lwz r5,172(r31) ; methodIndex + slwi r5,r5,2 ; methodIndex * 4 + lwzx r12,r5,r4 ; get function pointer + + lwz r4,28(r1) + lwz r5,32(r1) + lwz r6,36(r1) + lwz r7,40(r1) + lwz r8,44(r1) + lwz r9,48(r1) + lwz r10,52(r1) + + mtlr r12 + blrl + + mr r1,r31 + lwz r0,152(r1) + addi r1,r1,144 + mtlr r0 + lwz r31,-4(r1) + + blr + +.picsymbol_stub +L_invoke_count_words$stub: + .indirect_symbol _invoke_count_words + mflr r0 + bcl 20,31,L1$pb +L1$pb: + mflr r11 + addis r11,r11,ha16(L1$lz-L1$pb) + mtlr r0 + lwz r12,lo16(L1$lz-L1$pb)(r11) + mtctr r12 + addi r11,r11,lo16(L1$lz-L1$pb) + bctr +.lazy_symbol_pointer +L1$lz: + .indirect_symbol _invoke_count_words + .long dyld_stub_binding_helper + + +.picsymbol_stub +L_invoke_copy_to_stack$stub: + .indirect_symbol _invoke_copy_to_stack + mflr r0 + bcl 20,31,L2$pb +L2$pb: + mflr r11 + addis r11,r11,ha16(L2$lz-L2$pb) + mtlr r0 + lwz r12,lo16(L2$lz-L2$pb)(r11) + mtctr r12 + addi r11,r11,lo16(L2$lz-L2$pb) + bctr +.lazy_symbol_pointer +L2$lz: + .indirect_symbol _invoke_copy_to_stack + .long dyld_stub_binding_helper + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_riscv64.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_riscv64.S new file mode 100644 index 0000000000..4606523296 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_riscv64.S @@ -0,0 +1,89 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .set NGPREGS, 8 + .set NFPREGS, 8 + + .text + .globl _NS_InvokeByIndex + .type _NS_InvokeByIndex, @function +/* + * _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + * uint32_t paramCount, nsXPTCVariant* params) + */ +_NS_InvokeByIndex: + .cfi_startproc + addi sp, sp, -32 + .cfi_adjust_cfa_offset 32 + sd s0, 16(sp) + .cfi_rel_offset s0, 16 + sd s1, 8(sp) + .cfi_rel_offset s1, 8 + sd s2, 0(sp) + .cfi_rel_offset s2, 0 + sd ra, 24(sp) + .cfi_rel_offset ra, 24 + + mv s2, a0 + mv s1, a1 + mv s0, sp + .cfi_def_cfa_register s0 + + /* 16-bytes alignment */ + addiw a0, a2, 1 + andi a0, a0, -2 + slli a0, a0, 3 + sub sp, sp, a0 + mv a4, sp + + addi sp, sp, -8*(NGPREGS+NFPREGS) + mv a0, sp + addi a1, sp, 8*NGPREGS + + call invoke_copy_to_stack + + /* 1st argument is this */ + mv a0, s2 + + ld a1, 8(sp) + ld a2, 16(sp) + ld a3, 24(sp) + ld a4, 32(sp) + ld a5, 40(sp) + ld a6, 48(sp) + ld a7, 56(sp) + + fld fa0, 64(sp) + fld fa1, 72(sp) + fld fa2, 80(sp) + fld fa3, 88(sp) + fld fa4, 96(sp) + fld fa5, 104(sp) + fld fa6, 112(sp) + fld fa7, 120(sp) + + addi sp, sp, 8*(NGPREGS+NFPREGS) + + ld s2, 0(s2) + slliw s1, s1, 3 + add s2, s2, s1 + ld t0, 0(s2) + jalr t0 + + mv sp, s0 + .cfi_def_cfa_register sp + ld s0, 16(sp) + .cfi_restore s0 + ld s1, 8(sp) + .cfi_restore s1 + ld s2, 0(sp) + .cfi_restore s2 + ld ra, 24(sp) + .cfi_restore ra + addi sp, sp, 32 + .cfi_adjust_cfa_offset -32 + ret + .cfi_endproc + .size _NS_InvokeByIndex, . - _NS_InvokeByIndex + .section .note.GNU-stack, "", @progbits diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s new file mode 100644 index 0000000000..dfd6189f83 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s @@ -0,0 +1,86 @@ +/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + Platform specific code to invoke XPCOM methods on native objects + for sparcv9 Solaris. + + See the SPARC Compliance Definition (SCD) Chapter 3 + for more information about what is going on here, including + the use of BIAS (0x7ff). + The SCD is available from http://www.sparc.com/. +*/ + + .global NS_InvokeByIndex + .type NS_InvokeByIndex, #function + +/* + NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +*/ +NS_InvokeByIndex: + save %sp,-(128 + 64),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 64 + sll %i2,4,%l0 ! assume the worst case + ! paramCount * 2 * 8 bytes + cmp %l0, 0 ! are there any args? If not, + be .invoke ! no need to copy args to stack + nop + + sub %sp,%l0,%sp ! create the additional stack space + add %sp,0x7ff+136,%o0 ! step past the register window, the + ! struct result pointer and the 'this' slot + mov %i2,%o1 ! paramCount + call invoke_copy_to_stack + mov %i3,%o2 ! params + +! +! load arguments from stack into the outgoing registers +! BIAS is 0x7ff (2047) +! + +! load the %o1..5 64bit (extended word) output registers registers + ldx [%sp + 0x7ff + 136],%o1 ! %i1 + ldx [%sp + 0x7ff + 144],%o2 ! %i2 + ldx [%sp + 0x7ff + 152],%o3 ! %i3 + ldx [%sp + 0x7ff + 160],%o4 ! %i4 + ldx [%sp + 0x7ff + 168],%o5 ! %i5 + +! load the even number double registers starting with %f2 + ldd [%sp + 0x7ff + 136],%f2 + ldd [%sp + 0x7ff + 144],%f4 + ldd [%sp + 0x7ff + 152],%f6 + ldd [%sp + 0x7ff + 160],%f8 + ldd [%sp + 0x7ff + 168],%f10 + ldd [%sp + 0x7ff + 176],%f12 + ldd [%sp + 0x7ff + 184],%f14 + ldd [%sp + 0x7ff + 192],%f16 + ldd [%sp + 0x7ff + 200],%f18 + ldd [%sp + 0x7ff + 208],%f20 + ldd [%sp + 0x7ff + 216],%f22 + ldd [%sp + 0x7ff + 224],%f24 + ldd [%sp + 0x7ff + 232],%f26 + ldd [%sp + 0x7ff + 240],%f28 + ldd [%sp + 0x7ff + 248],%f30 + +! +! calculate the target address from the vtable +! +.invoke: + sll %i1,3,%l0 ! index *= 8 +! add %l0,16,%l0 ! there are 2 extra entries in the vTable (16bytes) + ldx [%i0],%l1 ! *that --> address of vtable + ldx [%l0 + %l1],%l0 ! that->vtable[index * 8 + 16] --> address + + jmpl %l0,%o7 ! call the routine + mov %i0,%o0 ! move 'this' pointer to out register + + mov %o0,%i0 ! propagate return value + ret + restore + + .size NS_InvokeByIndex, .-NS_InvokeByIndex diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s new file mode 100644 index 0000000000..36196805e8 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Platform specific code to invoke XPCOM methods on native objects for + * Linux/Sparc with gcc 3 ABI. + */ + .global NS_InvokeByIndex +/* + * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + * uint32_t paramCount, nsXPTCVariant* params); + * + */ +NS_InvokeByIndex: + save %sp,-(64 + 16),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 16 + mov %i2,%o0 ! paramCount + call invoke_count_words ! returns the required stack size in %o0 + mov %i3,%o1 ! params + + sll %o0,2,%l0 ! number of bytes + sub %sp,%l0,%sp ! create the additional stack space + + mov %sp,%o0 ! pointer for copied args + add %o0,72,%o0 ! step past the register window, the + ! struct result pointer and the 'this' slot + mov %i2,%o1 ! paramCount + call invoke_copy_to_stack + mov %i3,%o2 ! params +! +! calculate the target address from the vtable +! + ld [%i0],%l1 ! *that --> vTable + sll %i1,2,%i1 ! multiply index by 4 + add %i1,%l1,%l1 ! l1 now points to vTable entry + ld [%l1],%l0 ! target address + +.L5: ld [%sp + 88],%o5 +.L4: ld [%sp + 84],%o4 +.L3: ld [%sp + 80],%o3 +.L2: ld [%sp + 76],%o2 +.L1: ld [%sp + 72],%o1 +.L0: + jmpl %l0,%o7 ! call the routine +! always have a 'this', from the incoming 'that' + mov %i0,%o0 + + mov %o0,%i0 ! propagate return value + ret + restore diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s new file mode 100644 index 0000000000..893432a5e8 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + .global XPTC_InvokeByIndex +/* + XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +*/ +XPTC_InvokeByIndex: + save %sp,-(64 + 16),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 16 + mov %i2,%o0 ! paramCount + call invoke_count_words ! returns the required stack size in %o0 + mov %i3,%o1 ! params + + sll %o0,2,%l0 ! number of bytes + sub %sp,%l0,%sp ! create the additional stack space + + mov %sp,%o0 ! pointer for copied args + add %o0,72,%o0 ! step past the register window, the + ! struct result pointer and the 'this' slot + mov %i2,%o1 ! paramCount + call invoke_copy_to_stack + mov %i3,%o2 ! params +! +! calculate the target address from the vtable +! + add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?) + ld [%i0],%l1 ! *that --> vTable + sll %i1,3,%i1 + add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry + lduh [%l1],%l0 ! this adjustor + sll %l0,16,%l0 ! sign extend to 32 bits + sra %l0,16,%l0 + add %l0,%i0,%i0 ! adjust this + ld [%l1 + 4],%l0 ! target address + +.L5: ld [%sp + 88],%o5 +.L4: ld [%sp + 84],%o4 +.L3: ld [%sp + 80],%o3 +.L2: ld [%sp + 76],%o2 +.L1: ld [%sp + 72],%o1 +.L0: + jmpl %l0,%o7 ! call the routine +! always have a 'this', from the incoming 'that' + mov %i0,%o0 + + mov %o0,%i0 ! propagate return value + ret + restore diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s new file mode 100644 index 0000000000..1ef6953703 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + .global XPTC_InvokeByIndex +/* + XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +*/ +XPTC_InvokeByIndex: + save %sp,-(64 + 16),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 16 + mov %i2,%o0 ! paramCount + call invoke_count_words ! returns the required stack size in %o0 + mov %i3,%o1 ! params + + sll %o0,2,%l0 ! number of bytes + sub %sp,%l0,%sp ! create the additional stack space + + mov %sp,%o0 ! pointer for copied args + add %o0,72,%o0 ! step past the register window, the + ! struct result pointer and the 'this' slot + mov %i2,%o1 ! paramCount + call invoke_copy_to_stack + mov %i3,%o2 ! params +! +! calculate the target address from the vtable +! + add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?) + ld [%i0],%l1 ! *that --> vTable + sll %i1,3,%i1 + add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry + lduh [%l1],%l0 ! this adjustor + sll %l0,16,%l0 ! sign extend to 32 bits + sra %l0,16,%l0 + add %l0,%i0,%i0 ! adjust this + ld [%l1 + 4],%l0 ! target address + +.L5: ld [%sp + 88],%o5 +.L4: ld [%sp + 84],%o4 +.L3: ld [%sp + 80],%o3 +.L2: ld [%sp + 76],%o2 +.L1: ld [%sp + 72],%o1 +.L0: + jmpl %l0,%o7 ! call the routine +! always have a 'this', from the incoming 'that' + mov %i0,%o0 + + mov %o0,%i0 ! propagate return value + ret + restore diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_64_unix.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_64_unix.S new file mode 100644 index 0000000000..0cb7ff37c7 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_64_unix.S @@ -0,0 +1,117 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Darwin gives a leading '_' to symbols defined in C code. +#ifdef XP_DARWIN +#define SYM(x) _ ## x +#else +#define SYM(x) x +#endif + +#define CFI_STARTPROC .cfi_startproc +#define CFI_ENDPROC .cfi_endproc +#define CFI_DEF_CFA_OFFSET(offset) .cfi_def_cfa_offset offset +#define CFI_OFFSET(reg, offset) .cfi_offset reg, offset +#define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg +#define CFI_DEF_CFA(reg, offset) .cfi_def_cfa reg, offset + +.intel_syntax noprefix + +# nsresult NS_InvokeByIndex(nsISupports* this, uint32_t aVtableIndex, +# uint32_t argc, nsXPTCVariant* argv); +.text +.global SYM(NS_InvokeByIndex) +#ifndef XP_DARWIN +.type NS_InvokeByIndex, @function +#endif +.align 4 +SYM(NS_InvokeByIndex): + CFI_STARTPROC + push rbp + CFI_DEF_CFA_OFFSET(16) + CFI_OFFSET(6, -16) + mov rbp, rsp + CFI_DEF_CFA_REGISTER(6) + +# save r12 and r13 because we use them and they are callee saved. + push r12 + push r13 + CFI_OFFSET(12, -24) + CFI_OFFSET(13, -32) + +# save this and the vtable index because we need them after setting up the +# stack. + mov r12, rdi + mov r13, rsi + +# allocate space for stack arguments, in theory we only need 8 * (argc - 5) +# bytes because at least 5 arguments will go in registers, but for now it is +# just simpler to allocate 8 * argc bytes. Note that we treat the this +# pointer specially. + lea eax, [edx * 8] + sub rsp, rax + +# If there is an odd number of args the stack can be misaligned so realign it. + and rsp, 0xfffffffffffffff0 + +# pass the stack slot area to InvokeCopyToStack. + mov r8, rsp + +# setup space for the register slots: there are 5 integer ones and 8 floating +# point ones. So we need 104 bytes of space, but we allocate 112 to keep rsp +# aligned to 16 bytes. + sub rsp, 112 + +# the first argument to InvokeCopyToStack is the integer register area, and the +# second is the floating point area. + mov rdi, rsp + lea rsi, [rsp + 40] + +# The 3rd and 4th arguments to InvokeCopyToStack are already in the right +# registers. So now we can just call InvokeCopyToStack. + call SYM(InvokeCopyToStack) + +# setup this + mov rdi, r12 + +# copy the integer arguments into place. + mov rsi, [rsp] + mov rdx, [rsp + 8] + mov rcx, [rsp + 16] + mov r8, [rsp + 24] + mov r9, [rsp + 32] + +# copy the float arguments into place + movsd xmm0, [rsp + 40] + movsd xmm1, [rsp + 48] + movsd xmm2, [rsp + 56] + movsd xmm3, [rsp + 64] + movsd xmm4, [rsp + 72] + movsd xmm5, [rsp + 80] + movsd xmm6, [rsp + 88] + movsd xmm7, [rsp + 96] + +# get rid of the scratch space for registers + add rsp, 112 + +# load the function pointer and call + lea eax, [r13d * 8] + add rax, [rdi] + call [rax] + +# r12 and r13 were pushed relative to the old stack pointer which is now the +# frame pointer. + mov r12, [rbp - 0x8] + mov r13, [rbp - 0x10] + + mov rsp, rbp + pop rbp + CFI_DEF_CFA(7, 8) + ret + CFI_ENDPROC + +#ifndef XP_DARWIN +// Magic indicating no need for an executable stack +.section .note.GNU-stack, "", @progbits +#endif diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp new file mode 100644 index 0000000000..e6b7932e8d --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp @@ -0,0 +1,18 @@ +/* -*- Mode: C -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#if defined(__i386__) +#include "xptcinvoke_gcc_x86_unix.cpp" +#elif defined(__x86_64__) +#include "xptcinvoke_x86_64_unix.cpp" +#elif defined(__ppc__) +#include "xptcinvoke_ppc_rhapsody.cpp" +#elif defined(__arm__) +#include "xptcinvoke_arm.cpp" +#elif defined(__aarch64__) +#include "xptcinvoke_aarch64.cpp" +#else +#error unknown cpu architecture +#endif diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp new file mode 100644 index 0000000000..2e834a7e3c --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp @@ -0,0 +1,97 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" +#include "xptc_gcc_x86_unix.h" + +extern "C" { +static void ATTRIBUTE_USED __attribute__ ((regparm(3))) +invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d) +{ + for(uint32_t i = paramCount; i >0; i--, d++, s++) + { + if(s->IsIndirect()) + { + *((void**)d) = &s->val; + continue; + } + + switch(s->type) + { + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; + default : *((void**)d) = s->val.p; break; + } + } +} +} // extern "C" + +/* + EXPORT_XPCOM_API(nsresult) + NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + + Each param takes at most two 4-byte words. + It doesn't matter if we push too many words, and calculating the exact + amount takes time. + + that = ebp + 0x08 + methodIndex = ebp + 0x0c + paramCount = ebp + 0x10 + params = ebp + 0x14 + +*/ + +__asm__ ( + ".text\n\t" +/* alignment here seems unimportant here; this was 16, now it's 2 which + is what xptcstubs uses. */ + ".align 2\n\t" + ".globl " SYMBOL_UNDERSCORE "NS_InvokeByIndex\n\t" +#ifndef XP_MACOSX + ".type " SYMBOL_UNDERSCORE "NS_InvokeByIndex,@function\n" +#endif + SYMBOL_UNDERSCORE "NS_InvokeByIndex:\n\t" + "pushl %ebp\n\t" + "movl %esp, %ebp\n\t" + "movl 0x10(%ebp), %eax\n\t" + "leal 0(,%eax,8),%edx\n\t" + + /* set up call frame for method. */ + "subl %edx, %esp\n\t" /* make room for params. */ +/* Align to maximum x86 data size: 128 bits == 16 bytes == XMM register size. + * This is to avoid protection faults where SSE+ alignment of stack pointer + * is assumed and required, e.g. by GCC4's -ftree-vectorize option. + */ + "andl $0xfffffff0, %esp\n\t" /* drop(?) stack ptr to 128-bit align */ +/* $esp should be aligned to a 16-byte boundary here (note we include an + * additional 4 bytes in a later push instruction). This will ensure $ebp + * in the function called below is aligned to a 0x8 boundary. SSE instructions + * like movapd/movdqa expect memory operand to be aligned on a 16-byte + * boundary. The GCC compiler will generate the memory operand using $ebp + * with an 8-byte offset. + */ + "subl $0xc, %esp\n\t" /* lower again; push/call below will re-align */ + "movl %esp, %ecx\n\t" /* ecx = d */ + "movl 8(%ebp), %edx\n\t" /* edx = this */ + "pushl %edx\n\t" /* push this. esp % 16 == 0 */ + + "movl 0x14(%ebp), %edx\n\t" + "call " SYMBOL_UNDERSCORE "invoke_copy_to_stack\n\t" + "movl 0x08(%ebp), %ecx\n\t" /* 'that' */ + "movl (%ecx), %edx\n\t" + "movl 0x0c(%ebp), %eax\n\t" /* function index */ + "leal (%edx,%eax,4), %edx\n\t" + "call *(%edx)\n\t" + "movl %ebp, %esp\n\t" + "popl %ebp\n\t" + "ret\n" +#ifndef XP_MACOSX + ".size " SYMBOL_UNDERSCORE "NS_InvokeByIndex, . -" SYMBOL_UNDERSCORE "NS_InvokeByIndex\n\t" +#endif +); diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp new file mode 100644 index 0000000000..969029f13e --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp @@ -0,0 +1,129 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" + +// "This code is for IA64 only" + + +/* invoke_copy_to_stack() will copy from variant array 's' to + * the stack argument area 'mloc', the integer register area 'iloc', and + * the float register area 'floc'. + * + */ +extern "C" void +invoke_copy_to_stack(uint64_t* mloc, uint64_t* iloc, uint64_t* floc, + const uint32_t paramCount, nsXPTCVariant* s) +{ + uint64_t* dest = mloc; + uint32_t len = paramCount; + nsXPTCVariant* source = s; + + uint32_t indx; + uint32_t endlen; + endlen = (len > 7) ? 7 : len; + /* handle the memory arguments */ + for (indx = 7; indx < len; ++indx) + { + if (source[indx].IsPtrData()) + { +#ifdef __LP64__ + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].ptr; +#else + /* 32 bit pointer mode */ + uint32_t* adr = (uint32_t*) dest; + *(adr) = 0; + *(adr+1) = (uint32_t) source[indx].ptr; +#endif + } + else + switch (source[indx].type) + { + case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break; + case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break; + case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break; + case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break; + case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break; + case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break; + case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break; + case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break; + case nsXPTType::T_FLOAT : *(dest) = source[indx].val.u32; break; + case nsXPTType::T_DOUBLE: *(dest) = source[indx].val.u64; break; + case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break; + case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break; + case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break; + default: + // all the others are plain pointer types +#ifdef __LP64__ + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].val.p; +#else + { + /* 32 bit pointer mode */ + uint32_t* adr = (uint32_t*) dest; + *(adr) = 0; + *(adr+1) = (uint32_t) source[indx].val.p; + } +#endif + } + ++dest; + } + /* process register arguments */ + dest = iloc; + for (indx = 0; indx < endlen; ++indx) + { + if (source[indx].IsPtrData()) + { +#ifdef __LP64__ + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].ptr; +#else + /* 32 bit pointer mode */ + uint32_t* adr = (uint32_t*) dest; + *(adr) = 0; + *(adr+1) = (uint32_t) source[indx].ptr; +#endif + } + else + switch (source[indx].type) + { + case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break; + case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break; + case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break; + case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break; + case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break; + case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break; + case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break; + case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break; + case nsXPTType::T_FLOAT : + *((double*) (floc++)) = (double) source[indx].val.f; + break; + case nsXPTType::T_DOUBLE: + *((double*) (floc++)) = source[indx].val.d; + break; + case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break; + case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break; + case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break; + default: + // all the others are plain pointer types +#ifdef __LP64__ + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].val.p; +#else + { + /* 32 bit pointer mode */ + uint32_t* adr = (uint32_t*) dest; + *(adr) = 0; + *(adr+1) = (uint32_t) source[indx].val.p; + } +#endif + } + ++dest; + } + +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp new file mode 100644 index 0000000000..acd9de081b --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp @@ -0,0 +1,99 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" + +#include <stdint.h> + +// "This code is for IA64 only" + + +/* invoke_copy_to_stack() will copy from variant array 's' to + * the stack argument area 'mloc', the integer register area 'iloc', and + * the float register area 'floc'. + * + */ +extern "C" void +invoke_copy_to_stack(uint64_t* mloc, uint64_t* iloc, uint64_t* floc, + const uint32_t paramCount, nsXPTCVariant* s) +{ + uint64_t* dest = mloc; + uint32_t len = paramCount; + nsXPTCVariant* source = s; + + uint32_t indx; + uint32_t endlen; + endlen = (len > 7) ? 7 : len; + /* handle the memory arguments */ + for (indx = 7; indx < len; ++indx) + { + if (source[indx].IsPtrData()) + { + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].ptr; + } + else + switch (source[indx].type) + { + case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break; + case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break; + case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break; + case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break; + case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break; + case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break; + case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break; + case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break; + case nsXPTType::T_FLOAT : *(dest) = source[indx].val.u32; break; + case nsXPTType::T_DOUBLE: *(dest) = source[indx].val.u64; break; + case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break; + case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break; + case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break; + default: + // all the others are plain pointer types + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].val.p; + } + ++dest; + } + /* process register arguments */ + dest = iloc; + for (indx = 0; indx < endlen; ++indx) + { + if (source[indx].IsPtrData()) + { + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].ptr; + } + else + switch (source[indx].type) + { + case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break; + case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break; + case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break; + case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break; + case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break; + case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break; + case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break; + case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break; + case nsXPTType::T_FLOAT : + *((double*) (floc++)) = (double) source[indx].val.f; + break; + case nsXPTType::T_DOUBLE: + *((double*) (floc++)) = source[indx].val.d; + break; + case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break; + case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break; + case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break; + default: + // all the others are plain pointer types + /* 64 bit pointer mode */ + *((void**) dest) = source[indx].val.p; + } + ++dest; + } + +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp new file mode 100644 index 0000000000..dc111e4358 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp @@ -0,0 +1,144 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +/* Prototype specifies unmangled function name and disables unused warning */ +static void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s) +__asm__("invoke_copy_to_stack") __attribute__((used)); + +static void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer + + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if(s->IsPtrData()) + { + *d = (uint64_t)s->ptr; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : *d = (uint64_t)s->val.i8; break; + case nsXPTType::T_I16 : *d = (uint64_t)s->val.i16; break; + case nsXPTType::T_I32 : *d = (uint64_t)s->val.i32; break; + case nsXPTType::T_I64 : *d = (uint64_t)s->val.i64; break; + case nsXPTType::T_U8 : *d = (uint64_t)s->val.u8; break; + case nsXPTType::T_U16 : *d = (uint64_t)s->val.u16; break; + case nsXPTType::T_U32 : *d = (uint64_t)s->val.u32; break; + case nsXPTType::T_U64 : *d = (uint64_t)s->val.u64; break; + case nsXPTType::T_FLOAT : + if(i < NUM_ARG_REGS) + { + // convert floats to doubles if they are to be passed + // via registers so we can just deal with doubles later + union { uint64_t u64; double d; } t; + t.d = (double)s->val.f; + *d = t.u64; + } + else + // otherwise copy to stack normally + *d = (uint64_t)s->val.u32; + break; + case nsXPTType::T_DOUBLE : *d = (uint64_t)s->val.u64; break; + case nsXPTType::T_BOOL : *d = (uint64_t)s->val.b; break; + case nsXPTType::T_CHAR : *d = (uint64_t)s->val.c; break; + case nsXPTType::T_WCHAR : *d = (uint64_t)s->val.wc; break; + default: + // all the others are plain pointer types + *d = (uint64_t)s->val.p; + break; + } + } +} + +/* + * EXPORT_XPCOM_API(nsresult) + * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + * uint32_t paramCount, nsXPTCVariant* params) + */ +__asm__( + "#### NS_InvokeByIndex ####\n" +".text\n\t" + ".align 5\n\t" + ".globl NS_InvokeByIndex\n\t" + ".ent NS_InvokeByIndex\n" +"NS_InvokeByIndex:\n\t" + ".frame $15,32,$26,0\n\t" + ".mask 0x4008000,-32\n\t" + "ldgp $29,0($27)\n" +"$NS_InvokeByIndex..ng:\n\t" + "subq $30,32,$30\n\t" + "stq $26,0($30)\n\t" + "stq $15,8($30)\n\t" + "bis $30,$30,$15\n\t" + ".prologue 1\n\t" + + /* + * Allocate enough stack space to hold the greater of 6 or "paramCount"+1 + * parameters. (+1 for "this" pointer) Room for at least 6 parameters + * is required for storage of those passed via registers. + */ + + "bis $31,5,$2\n\t" /* count = MAX(5, "paramCount") */ + "cmplt $2,$18,$1\n\t" + "cmovne $1,$18,$2\n\t" + "s8addq $2,16,$1\n\t" /* room for count+1 params (8 bytes each) */ + "bic $1,15,$1\n\t" /* stack space is rounded up to 0 % 16 */ + "subq $30,$1,$30\n\t" + + "stq $16,0($30)\n\t" /* save "that" (as "this" pointer) */ + "stq $17,16($15)\n\t" /* save "methodIndex" */ + + "addq $30,8,$16\n\t" /* pass stack pointer */ + "bis $18,$18,$17\n\t" /* pass "paramCount" */ + "bis $19,$19,$18\n\t" /* pass "params" */ + "bsr $26,$invoke_copy_to_stack..ng\n\t" /* call invoke_copy_to_stack */ + + /* + * Copy the first 6 parameters to registers and remove from stack frame. + * Both the integer and floating point registers are set for each parameter + * except the first which is the "this" pointer. (integer only) + * The floating point registers are all set as doubles since the + * invoke_copy_to_stack function should have converted the floats. + */ + "ldq $16,0($30)\n\t" /* integer registers */ + "ldq $17,8($30)\n\t" + "ldq $18,16($30)\n\t" + "ldq $19,24($30)\n\t" + "ldq $20,32($30)\n\t" + "ldq $21,40($30)\n\t" + "ldt $f17,8($30)\n\t" /* floating point registers */ + "ldt $f18,16($30)\n\t" + "ldt $f19,24($30)\n\t" + "ldt $f20,32($30)\n\t" + "ldt $f21,40($30)\n\t" + + "addq $30,48,$30\n\t" /* remove params from stack */ + + /* + * Call the virtual function with the constructed stack frame. + */ + "bis $16,$16,$1\n\t" /* load "this" */ + "ldq $2,16($15)\n\t" /* load "methodIndex" */ + "ldq $1,0($1)\n\t" /* load vtable */ + "s8addq $2,$31,$2\n\t" /* vtable index = "methodIndex" * 8 */ + "addq $1,$2,$1\n\t" + "ldq $27,0($1)\n\t" /* load address of function */ + "jsr $26,($27),0\n\t" /* call virtual function */ + "ldgp $29,0($26)\n\t" + + "bis $15,$15,$30\n\t" + "ldq $26,0($30)\n\t" + "ldq $15,8($30)\n\t" + "addq $30,32,$30\n\t" + "ret $31,($26),1\n\t" + ".end NS_InvokeByIndex" + ); diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp new file mode 100644 index 0000000000..c5fa2f94bd --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp @@ -0,0 +1,194 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + + +static uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t overflow = 0, gpr = 1 /*this*/, fpr = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + if (gpr < 5) gpr++; else overflow++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + if (gpr < 5) gpr++; else overflow++; + break; + case nsXPTType::T_I64 : + if (gpr < 4) gpr+=2; else gpr=5, overflow+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + if (gpr < 5) gpr++; else overflow++; + break; + case nsXPTType::T_U64 : + if (gpr < 4) gpr+=2; else gpr=5, overflow+=2; + break; + case nsXPTType::T_FLOAT : + if (fpr < 2) fpr++; else overflow++; + break; + case nsXPTType::T_DOUBLE : + if (fpr < 2) fpr++; else overflow+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + if (gpr < 5) gpr++; else overflow++; + break; + default: + // all the others are plain pointer types + if (gpr < 5) gpr++; else overflow++; + break; + } + } + /* Round up number of overflow words to ensure stack + stays aligned to 8 bytes. */ + return (overflow + 1) & ~1; +} + +static void +invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d_ov, uint32_t overflow) +{ + uint32_t *d_gpr = d_ov + overflow; + uint64_t *d_fpr = (uint64_t *)(d_gpr + 4); + uint32_t gpr = 1 /*this*/, fpr = 0; + + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + if (gpr < 5) + *((void**)d_gpr) = s->ptr, d_gpr++, gpr++; + else + *((void**)d_ov ) = s->ptr, d_ov++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + if (gpr < 5) + *((int32_t*) d_gpr) = s->val.i8, d_gpr++, gpr++; + else + *((int32_t*) d_ov ) = s->val.i8, d_ov++; + break; + case nsXPTType::T_I16 : + if (gpr < 5) + *((int32_t*) d_gpr) = s->val.i16, d_gpr++, gpr++; + else + *((int32_t*) d_ov ) = s->val.i16, d_ov++; + break; + case nsXPTType::T_I32 : + if (gpr < 5) + *((int32_t*) d_gpr) = s->val.i32, d_gpr++, gpr++; + else + *((int32_t*) d_ov ) = s->val.i32, d_ov++; + break; + case nsXPTType::T_I64 : + if (gpr < 4) + *((int64_t*) d_gpr) = s->val.i64, d_gpr+=2, gpr+=2; + else + *((int64_t*) d_ov ) = s->val.i64, d_ov+=2, gpr=5; + break; + case nsXPTType::T_U8 : + if (gpr < 5) + *((uint32_t*) d_gpr) = s->val.u8, d_gpr++, gpr++; + else + *((uint32_t*) d_ov ) = s->val.u8, d_ov++; + break; + case nsXPTType::T_U16 : + if (gpr < 5) + *((uint32_t*)d_gpr) = s->val.u16, d_gpr++, gpr++; + else + *((uint32_t*)d_ov ) = s->val.u16, d_ov++; + break; + case nsXPTType::T_U32 : + if (gpr < 5) + *((uint32_t*)d_gpr) = s->val.u32, d_gpr++, gpr++; + else + *((uint32_t*)d_ov ) = s->val.u32, d_ov++; + break; + case nsXPTType::T_U64 : + if (gpr < 4) + *((uint64_t*)d_gpr) = s->val.u64, d_gpr+=2, gpr+=2; + else + *((uint64_t*)d_ov ) = s->val.u64, d_ov+=2, gpr=5; + break; + case nsXPTType::T_FLOAT : + if (fpr < 2) + *((float*) d_fpr) = s->val.f, d_fpr++, fpr++; + else + *((float*) d_ov ) = s->val.f, d_ov++; + break; + case nsXPTType::T_DOUBLE : + if (fpr < 2) + *((double*) d_fpr) = s->val.d, d_fpr++, fpr++; + else + *((double*) d_ov ) = s->val.d, d_ov+=2; + break; + case nsXPTType::T_BOOL : + if (gpr < 5) + *((uint32_t*)d_gpr) = s->val.b, d_gpr++, gpr++; + else + *((uint32_t*)d_ov ) = s->val.b, d_ov++; + break; + case nsXPTType::T_CHAR : + if (gpr < 5) + *((uint32_t*)d_gpr) = s->val.c, d_gpr++, gpr++; + else + *((uint32_t*)d_ov ) = s->val.c, d_ov++; + break; + case nsXPTType::T_WCHAR : + if (gpr < 5) + *((uint32_t*)d_gpr) = s->val.wc, d_gpr++, gpr++; + else + *((uint32_t*)d_ov ) = s->val.wc, d_ov++; + break; + default: + // all the others are plain pointer types + if (gpr < 5) + *((void**) d_gpr) = s->val.p, d_gpr++, gpr++; + else + *((void**) d_ov ) = s->val.p, d_ov++; + break; + } + } +} + +typedef nsresult (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t, uint32_t, double, double); + +// Avoid AddressSanitizer instrumentation for the next function because it +// depends on __builtin_alloca behavior and alignment that cannot be relied on +// once the function is compiled with a version of ASan that has dynamic-alloca +// instrumentation enabled. + +MOZ_ASAN_IGNORE +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + vtable_func *vtable = *reinterpret_cast<vtable_func **>(that); + vtable_func method = vtable[methodIndex]; + uint32_t overflow = invoke_count_words (paramCount, params); + uint32_t *stack_space = reinterpret_cast<uint32_t *>(__builtin_alloca((overflow + 8 /* 4 32-bits gpr + 2 64-bits fpr */) * 4)); + + invoke_copy_to_stack(paramCount, params, stack_space, overflow); + + uint32_t *d_gpr = stack_space + overflow; + double *d_fpr = reinterpret_cast<double *>(d_gpr + 4); + + return method(that, d_gpr[0], d_gpr[1], d_gpr[2], d_gpr[3], d_fpr[0], d_fpr[1]); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp new file mode 100644 index 0000000000..1be12d4ad3 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp @@ -0,0 +1,189 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + + +static uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t overflow = 0, gpr = 1 /*this*/, fpr = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsIndirect()) + { + if (gpr < 5) gpr++; else overflow++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + case nsXPTType::T_I64 : + if (gpr < 5) gpr++; else overflow++; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + case nsXPTType::T_U64 : + if (gpr < 5) gpr++; else overflow++; + break; + case nsXPTType::T_FLOAT : + case nsXPTType::T_DOUBLE : + if (fpr < 4) fpr++; else overflow++; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + if (gpr < 5) gpr++; else overflow++; + break; + default: + // all the others are plain pointer types + if (gpr < 5) gpr++; else overflow++; + break; + } + } + /* Round up number of overflow words to ensure stack + stays aligned to 8 bytes. */ + return (overflow + 1) & ~1; +} + +static void +invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint64_t* d_ov, uint32_t overflow) +{ + uint64_t *d_gpr = d_ov + overflow; + uint64_t *d_fpr = (uint64_t *)(d_gpr + 4); + uint32_t gpr = 1 /*this*/, fpr = 0; + + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsIndirect()) + { + if (gpr < 5) + *((void**)d_gpr) = (void *) &s->val, d_gpr++, gpr++; + else + *((void**)d_ov ) = (void *) &s->val, d_ov++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + if (gpr < 5) + *((int64_t*) d_gpr) = s->val.i8, d_gpr++, gpr++; + else + *((int64_t*) d_ov ) = s->val.i8, d_ov++; + break; + case nsXPTType::T_I16 : + if (gpr < 5) + *((int64_t*) d_gpr) = s->val.i16, d_gpr++, gpr++; + else + *((int64_t*) d_ov ) = s->val.i16, d_ov++; + break; + case nsXPTType::T_I32 : + if (gpr < 5) + *((int64_t*) d_gpr) = s->val.i32, d_gpr++, gpr++; + else + *((int64_t*) d_ov ) = s->val.i32, d_ov++; + break; + case nsXPTType::T_I64 : + if (gpr < 5) + *((int64_t*) d_gpr) = s->val.i64, d_gpr++, gpr++; + else + *((int64_t*) d_ov ) = s->val.i64, d_ov++; + break; + case nsXPTType::T_U8 : + if (gpr < 5) + *((uint64_t*) d_gpr) = s->val.u8, d_gpr++, gpr++; + else + *((uint64_t*) d_ov ) = s->val.u8, d_ov++; + break; + case nsXPTType::T_U16 : + if (gpr < 5) + *((uint64_t*)d_gpr) = s->val.u16, d_gpr++, gpr++; + else + *((uint64_t*)d_ov ) = s->val.u16, d_ov++; + break; + case nsXPTType::T_U32 : + if (gpr < 5) + *((uint64_t*)d_gpr) = s->val.u32, d_gpr++, gpr++; + else + *((uint64_t*)d_ov ) = s->val.u32, d_ov++; + break; + case nsXPTType::T_U64 : + if (gpr < 5) + *((uint64_t*)d_gpr) = s->val.u64, d_gpr++, gpr++; + else + *((uint64_t*)d_ov ) = s->val.u64, d_ov++; + break; + case nsXPTType::T_FLOAT : + if (fpr < 4) + *((float*) d_fpr) = s->val.f, d_fpr++, fpr++; + else + *(((float*) d_ov )+1) = s->val.f, d_ov++; + break; + case nsXPTType::T_DOUBLE : + if (fpr < 4) + *((double*) d_fpr) = s->val.d, d_fpr++, fpr++; + else + *((double*) d_ov ) = s->val.d, d_ov++; + break; + case nsXPTType::T_BOOL : + if (gpr < 5) + *((uint64_t*)d_gpr) = s->val.b, d_gpr++, gpr++; + else + *((uint64_t*)d_ov ) = s->val.b, d_ov++; + break; + case nsXPTType::T_CHAR : + if (gpr < 5) + *((uint64_t*)d_gpr) = s->val.c, d_gpr++, gpr++; + else + *((uint64_t*)d_ov ) = s->val.c, d_ov++; + break; + case nsXPTType::T_WCHAR : + if (gpr < 5) + *((uint64_t*)d_gpr) = s->val.wc, d_gpr++, gpr++; + else + *((uint64_t*)d_ov ) = s->val.wc, d_ov++; + break; + default: + // all the others are plain pointer types + if (gpr < 5) + *((void**) d_gpr) = s->val.p, d_gpr++, gpr++; + else + *((void**) d_ov ) = s->val.p, d_ov++; + break; + } + } +} + +typedef nsresult (*vtable_func)(nsISupports *, uint64_t, uint64_t, uint64_t, uint64_t, double, double, double, double); + +// Avoid AddressSanitizer instrumentation for the next function because it +// depends on __builtin_alloca behavior and alignment that cannot be relied on +// once the function is compiled with a version of ASan that has dynamic-alloca +// instrumentation enabled. + +MOZ_ASAN_IGNORE +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + vtable_func *vtable = *reinterpret_cast<vtable_func **>(that); + vtable_func method = vtable[methodIndex]; + uint64_t overflow = invoke_count_words (paramCount, params); + uint64_t *stack_space = reinterpret_cast<uint64_t *>(__builtin_alloca((overflow + 8 /* 4 64-bits gpr + 4 64-bits fpr */) * 8)); + uint64_t result; + + invoke_copy_to_stack(paramCount, params, stack_space, overflow); + + uint64_t *d_gpr = stack_space + overflow; + double *d_fpr = reinterpret_cast<double *>(d_gpr + 4); + + return method(that, d_gpr[0], d_gpr[1], d_gpr[2], d_gpr[3], d_fpr[0], d_fpr[1], d_fpr[2], d_fpr[3]); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp new file mode 100644 index 0000000000..61bb7b2efd --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp @@ -0,0 +1,100 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Platform specific code to invoke XPCOM methods on native objects + +#include "xptcprivate.h" + +extern "C" void invoke_copy_to_stack(uint64_t* gpregs, double* fpregs, + uint32_t paramCount, nsXPTCVariant* s, + uint64_t* d) { + static const uint32_t GPR_COUNT = 8; + static const uint32_t FPR_COUNT = 8; + + uint32_t nr_gpr = 1; // skip one GPR register for "this" + uint32_t nr_fpr = 0; + uint64_t value = 0; + + for (uint32_t i = 0; i < paramCount; i++, s++) { + if (s->IsIndirect()) { + value = (uint64_t)&s->val; + } else { + switch (s->type) { + case nsXPTType::T_FLOAT: + break; + case nsXPTType::T_DOUBLE: + break; + case nsXPTType::T_I8: + value = s->val.i8; + break; + case nsXPTType::T_I16: + value = s->val.i16; + break; + case nsXPTType::T_I32: + value = s->val.i32; + break; + case nsXPTType::T_I64: + value = s->val.i64; + break; + case nsXPTType::T_U8: + value = s->val.u8; + break; + case nsXPTType::T_U16: + value = s->val.u16; + break; + case nsXPTType::T_U32: + value = s->val.u32; + break; + case nsXPTType::T_U64: + value = s->val.u64; + break; + case nsXPTType::T_BOOL: + value = s->val.b; + break; + case nsXPTType::T_CHAR: + value = s->val.c; + break; + case nsXPTType::T_WCHAR: + value = s->val.wc; + break; + default: + value = (uint64_t)s->val.p; + break; + } + } + + if (!s->IsIndirect() && s->type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) { + fpregs[nr_fpr++] = s->val.d; + } else if (nr_gpr < GPR_COUNT) { + memcpy(&gpregs[nr_gpr++], &(s->val.d), sizeof(s->val.d)); + } else { + memcpy(d++, &(s->val.d), sizeof(s->val.d)); + } + } else if (!s->IsIndirect() && s->type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) { + memcpy(&fpregs[nr_fpr++], &(s->val.f), sizeof(s->val.f)); + } else if (nr_gpr < GPR_COUNT) { + memcpy(&gpregs[nr_gpr++], &(s->val.f), sizeof(s->val.f)); + } else { + memcpy(d++, &(s->val.f), sizeof(s->val.f)); + } + } else { + if (nr_gpr < GPR_COUNT) { + gpregs[nr_gpr++] = value; + } else { + *d++ = value; + } + } + } +} + +extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, + nsXPTCVariant* params); +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, uint32_t paramCount, + nsXPTCVariant* params) { + return _NS_InvokeByIndex(that, methodIndex, paramCount, params); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp new file mode 100644 index 0000000000..b811730c5b --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp @@ -0,0 +1,99 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * Version: MPL 1.1 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* This code is for MIPS using the O32 ABI. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#include <stdint.h> + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + // Count a word for a0 even though it's never stored or loaded + // We do this only for alignment of register pairs. + uint32_t result = 1; + for (uint32_t i = 0; i < paramCount; i++, result++, s++) + { + if (s->IsIndirect()) + continue; + + switch(s->type) + { + case nsXPTType::T_I64 : + case nsXPTType::T_U64 : + case nsXPTType::T_DOUBLE : + if (result & 1) + result++; + result++; + break; + + default: + break; + } + } + return (result + 1) & ~(uint32_t)1; +} + +extern "C" void +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, + nsXPTCVariant* s) +{ + // Skip the unused a0 slot, which we keep only for register pair alignment. + d++; + + for (uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if (s->IsIndirect()) + { + *((void**)d) = (void*) &s->val; + continue; + } + + switch(s->type) + { + case nsXPTType::T_I8 : *d = (uint32_t) s->val.i8; break; + case nsXPTType::T_I16 : *d = (uint32_t) s->val.i16; break; + case nsXPTType::T_I32 : *d = (uint32_t) s->val.i32; break; + case nsXPTType::T_I64 : + if ((intptr_t)d & 4) d++; + *((int64_t*) d) = s->val.i64; d++; + break; + case nsXPTType::T_U8 : *d = (uint32_t) s->val.u8; break; + case nsXPTType::T_U16 : *d = (uint32_t) s->val.u16; break; + case nsXPTType::T_U32 : *d = (uint32_t) s->val.u32; break; + case nsXPTType::T_U64 : + if ((intptr_t)d & 4) d++; + *((uint64_t*) d) = s->val.u64; d++; + break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : + if ((intptr_t)d & 4) d++; + *((double*) d) = s->val.d; d++; + break; + case nsXPTType::T_BOOL : *d = (bool) s->val.b; break; + case nsXPTType::T_CHAR : *d = (char) s->val.c; break; + case nsXPTType::T_WCHAR : *d = (wchar_t) s->val.wc; break; + default: + *((void**)d) = s->val.p; + break; + } + } +} + +extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, + nsXPTCVariant* params); + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + return _NS_InvokeByIndex(that, methodIndex, paramCount, params); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp new file mode 100644 index 0000000000..d10320a997 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp @@ -0,0 +1,144 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#if (_MIPS_SIM != _ABIN32) && (_MIPS_SIM != _ABI64) +#error "This code is for MIPS n32/n64 only" +#endif + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + return paramCount; +} + +extern "C" void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, + nsXPTCVariant* s, uint64_t *regs) +{ +#define N_ARG_REGS 7 /* 8 regs minus 1 for "this" ptr */ + + for (uint32_t i = 0; i < paramCount; i++, s++) + { + if (s->IsIndirect()) { + if (i < N_ARG_REGS) + regs[i] = (uint64_t) &s->val; + else + *d++ = (uint64_t) &s->val; + continue; + } + switch (s->type) { + // + // signed types first + // + case nsXPTType::T_I8: + if (i < N_ARG_REGS) + ((int64_t*)regs)[i] = s->val.i8; + else + *d++ = s->val.i8; + break; + case nsXPTType::T_I16: + if (i < N_ARG_REGS) + ((int64_t*)regs)[i] = s->val.i16; + else + *d++ = s->val.i16; + break; + case nsXPTType::T_I32: + if (i < N_ARG_REGS) + ((int64_t*)regs)[i] = s->val.i32; + else + *d++ = s->val.i32; + break; + case nsXPTType::T_I64: + if (i < N_ARG_REGS) + ((int64_t*)regs)[i] = s->val.i64; + else + *d++ = s->val.i64; + break; + // + // unsigned types next + // + case nsXPTType::T_U8: + if (i < N_ARG_REGS) + regs[i] = s->val.u8; + else + *d++ = s->val.u8; + break; + case nsXPTType::T_U16: + if (i < N_ARG_REGS) + regs[i] = s->val.u16; + else + *d++ = s->val.u16; + break; + case nsXPTType::T_U32: + if (i < N_ARG_REGS) + // 32-bit values need to be sign-extended + // in register, so use the signed value. + regs[i] = s->val.i32; + else + *d++ = s->val.u32; + break; + case nsXPTType::T_U64: + if (i < N_ARG_REGS) + regs[i] = s->val.u64; + else + *d++ = s->val.u64; + break; + case nsXPTType::T_FLOAT: + // the float data formate must not be converted! + // Just only copy without conversion. + if (i < N_ARG_REGS) + *(float*)®s[i] = s->val.f; + else + *(float*)d++ = s->val.f; + break; + case nsXPTType::T_DOUBLE: + if (i < N_ARG_REGS) + *(double*)®s[i] = s->val.d; + else + *(double*)d++ = s->val.d; + break; + case nsXPTType::T_BOOL: + if (i < N_ARG_REGS) + regs[i] = s->val.b; + else + *d++ = s->val.b; + break; + case nsXPTType::T_CHAR: + if (i < N_ARG_REGS) + regs[i] = s->val.c; + else + *d++ = s->val.c; + break; + case nsXPTType::T_WCHAR: + if (i < N_ARG_REGS) + regs[i] = s->val.wc; + else + *d++ = s->val.wc; + break; + default: + // all the others are plain pointer types + if (i < N_ARG_REGS) + regs[i] = (uint64_t)s->val.p; + else + *d++ = (uint64_t)s->val.p; + break; + } + } +} + +extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, + nsXPTCVariant* params); + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + return _NS_InvokeByIndex(that, methodIndex, paramCount, params); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp new file mode 100644 index 0000000000..c0c3e510fa --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp @@ -0,0 +1,148 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" + +#if _HPUX +#error "This code is for HP-PA RISC 32 bit mode only" +#endif + +#include <alloca.h> + +typedef unsigned nsXPCVariant; + +extern "C" int32_t +invoke_count_bytes(nsISupports* that, const uint32_t methodIndex, + const uint32_t paramCount, const nsXPTCVariant* s) +{ + int32_t result = 4; /* variant records do not include self pointer */ + + /* counts the number of bytes required by the argument stack, + 64 bit integer, and double requires 8 bytes. All else requires + 4 bytes. + */ + + { + uint32_t indx; + for (indx = paramCount; indx > 0; --indx, ++s) + { + if (! s->IsPtrData()) + { + if (s->type == nsXPTType::T_I64 || s->type == nsXPTType::T_U64 || + s->type == nsXPTType::T_DOUBLE) + { + /* 64 bit integer and double aligned on 8 byte boundaries */ + result += (result & 4) + 8; + continue; + } + } + result += 4; /* all other cases use 4 bytes */ + } + } + result -= 72; /* existing stack buffer is 72 bytes */ + if (result < 0) + return 0; + { + /* round up to 64 bytes boundary */ + int32_t remainder = result & 63; + return (remainder == 0) ? result : (result + 64 - remainder); + } +} + +extern "C" uint32_t +invoke_copy_to_stack(uint32_t* d, + const uint32_t paramCount, nsXPTCVariant* s) +{ + + typedef struct + { + uint32_t hi; + uint32_t lo; + } DU; + + uint32_t* dest = d; + nsXPTCVariant* source = s; + /* we clobber param vars by copying stuff on stack, have to use local var */ + + uint32_t floatflags = 0; + /* flag indicating which floating point registers to load */ + + uint32_t regwords = 1; /* register 26 is reserved for ptr to 'that' */ + uint32_t indx; + + for (indx = paramCount; indx > 0; --indx, --dest, ++source) + { + if (source->IsPtrData()) + { + *((void**) dest) = source->ptr; + ++regwords; + continue; + } + switch (source->type) + { + case nsXPTType::T_I8 : *((int32_t*) dest) = source->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) dest) = source->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) dest) = source->val.i32; break; + case nsXPTType::T_I64 : + case nsXPTType::T_U64 : + if (regwords & 1) + { + /* align on double word boundary */ + --dest; + ++regwords; + } + *((uint32_t*) dest) = ((DU *) source)->lo; + *((uint32_t*) --dest) = ((DU *) source)->hi; + /* big endian - hi word in low addr */ + regwords += 2; + continue; + case nsXPTType::T_DOUBLE : + if (regwords & 1) + { + /* align on double word boundary */ + --dest; + ++regwords; + } + switch (regwords) /* load double precision float register */ + { + case 2: + floatflags |= 1; + } + *((uint32_t*) dest) = ((DU *) source)->lo; + *((uint32_t*) --dest) = ((DU *) source)->hi; + /* big endian - hi word in low addr */ + regwords += 2; + continue; + case nsXPTType::T_FLOAT : + switch (regwords) /* load single precision float register */ + { + case 1: + floatflags |= 2; + break; + case 2: + floatflags |= 4; + break; + case 3: + floatflags |= 8; + } + *((float*) dest) = source->val.f; + break; + case nsXPTType::T_U8 : *((uint32_t*) (dest)) = source->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*) (dest)) = source->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*) (dest)) = source->val.u32; break; + case nsXPTType::T_BOOL : *((uint32_t*) (dest)) = source->val.b; break; + case nsXPTType::T_CHAR : *((uint32_t*) (dest)) = source->val.c; break; + case nsXPTType::T_WCHAR : *((int32_t*) (dest)) = source->val.wc; break; + + default: + // all the others are plain pointer types + *((void**) dest) = source->val.p; + } + ++regwords; + } + return floatflags; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp new file mode 100644 index 0000000000..f7673bb29d --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp @@ -0,0 +1,140 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Platform specific code to invoke XPCOM methods on native objects + +#include "xptcprivate.h" + +// The purpose of NS_InvokeByIndex() is to map a platform +// independent call to the platform ABI. To do that, +// NS_InvokeByIndex() has to determine the method to call via vtable +// access. The parameters for the method are read from the +// nsXPTCVariant* and prepared for the native ABI. +// +// Prior to POWER8, all 64-bit Power ISA systems used ELF v1 ABI, found +// here: +// https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html +// and in particular: +// https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-CALL +// Little-endian ppc64le, however, uses ELF v2 ABI, which is here: +// http://openpowerfoundation.org/wp-content/uploads/resources/leabi/leabi-20170510.pdf +// and in particular section 2.2, page 22. However, most big-endian ppc64 +// systems still use ELF v1, so this file should support both. + +// 7 integral parameters are passed in registers, not including |this| +// (i.e., r3-r10, with r3 being |this|). +const uint32_t GPR_COUNT = 7; + +// 13 floating point parameters are passed in registers, either single or +// double precision (i.e., f1-f13). +const uint32_t FPR_COUNT = 13; + +// Both ABIs use the same register assignment strategy, as per this +// example from V1 ABI section 3.2.3 and V2 ABI section 2.2.3.2 [page 43]: +// +// typedef struct { +// int a; +// double dd; +// } sparm; +// sparm s, t; +// int c, d, e; +// long double ld; +// double ff, gg, hh; +// +// x = func(c, ff, d, ld, s, gg, t, e, hh); +// +// Parameter Register Offset in parameter save area +// c r3 0-7 (not stored in parameter save area) +// ff f1 8-15 (not stored) +// d r5 16-23 (not stored) +// ld f2,f3 24-39 (not stored) +// s r8,r9 40-55 (not stored) +// gg f4 56-63 (not stored) +// t (none) 64-79 (stored in parameter save area) +// e (none) 80-87 (stored) +// hh f5 88-95 (not stored) +// +// i.e., each successive FPR usage skips a GPR, but not the other way around. + +extern "C" void invoke_copy_to_stack(uint64_t* gpregs, double* fpregs, + uint32_t paramCount, nsXPTCVariant* s, + uint64_t* d) +{ + uint32_t nr_gpr = 0u; + uint32_t nr_fpr = 0u; + uint64_t value = 0u; + + for (uint32_t i = 0; i < paramCount; i++, s++) { + if (s->IsIndirect()) + value = (uint64_t) &s->val; + else { + switch (s->type) { + case nsXPTType::T_FLOAT: break; + case nsXPTType::T_DOUBLE: break; + case nsXPTType::T_I8: value = s->val.i8; break; + case nsXPTType::T_I16: value = s->val.i16; break; + case nsXPTType::T_I32: value = s->val.i32; break; + case nsXPTType::T_I64: value = s->val.i64; break; + case nsXPTType::T_U8: value = s->val.u8; break; + case nsXPTType::T_U16: value = s->val.u16; break; + case nsXPTType::T_U32: value = s->val.u32; break; + case nsXPTType::T_U64: value = s->val.u64; break; + case nsXPTType::T_BOOL: value = s->val.b; break; + case nsXPTType::T_CHAR: value = s->val.c; break; + case nsXPTType::T_WCHAR: value = s->val.wc; break; + default: value = (uint64_t) s->val.p; break; + } + } + + if (!s->IsIndirect() && s->type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) { + fpregs[nr_fpr++] = s->val.d; + // Even if we have enough FPRs, still skip space in + // the parameter area if we ran out of placeholder GPRs. + if (nr_gpr < GPR_COUNT) { + nr_gpr++; + } else { + d++; + } + } else { + *((double *)d) = s->val.d; + d++; + } + } + else if (!s->IsIndirect() && s->type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) { + // Single-precision floats are passed in FPRs too. + fpregs[nr_fpr++] = s->val.f; + if (nr_gpr < GPR_COUNT) { + nr_gpr++; + } else { + d++; + } + } else { +#ifdef __LITTLE_ENDIAN__ + *((float *)d) = s->val.f; +#else + // Big endian needs adjustment to point to the least + // significant word. + float* p = (float*)d; + p++; + *p = s->val.f; +#endif + d++; + } + } + else { + if (nr_gpr < GPR_COUNT) { + gpregs[nr_gpr++] = value; + } else { + *d++ = value; + } + } + } +} + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, uint32_t paramCount, + nsXPTCVariant* params); diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp new file mode 100644 index 0000000000..d894224539 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp @@ -0,0 +1,73 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#ifndef AIX +#error "This code is for PowerPC only" +#endif + +extern "C" void +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s, double *fprData) +{ +/* + We need to copy the parameters for this function to locals and use them + from there since the parameters occupy the same stack space as the stack + we're trying to populate. +*/ + uint32_t *l_d = d; + nsXPTCVariant *l_s = s; + uint32_t l_paramCount = paramCount, fpCount = 0; + double *l_fprData = fprData; + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + + for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++) + { + if(l_s->IsPtrData()) + { + *((void**)l_d) = l_s->ptr; + continue; + } + switch(l_s->type) + { + case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break; + case nsXPTType::T_I64 : + case nsXPTType::T_U64 : + *((uint32_t*) l_d++) = ((DU *)l_s)->hi; + *((uint32_t*) l_d) = ((DU *)l_s)->lo; + break; + case nsXPTType::T_DOUBLE : + *((uint32_t*) l_d++) = ((DU *)l_s)->hi; + *((uint32_t*) l_d) = ((DU *)l_s)->lo; + if(fpCount < 13) + l_fprData[fpCount++] = l_s->val.d; + break; + case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break; + case nsXPTType::T_FLOAT : + *((float*) l_d) = l_s->val.f; + if(fpCount < 13) + l_fprData[fpCount++] = l_s->val.f; + break; + case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break; + case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break; + case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)l_d) = l_s->val.p; + break; + } + } +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp new file mode 100644 index 0000000000..588f1266c0 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp @@ -0,0 +1,62 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#ifdef _AIX + +extern "C" void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s, double *fprData) +{ +/* + We need to copy the parameters for this function to locals and use them + from there since the parameters occupy the same stack space as the stack + we're trying to populate. +*/ + uint64_t *l_d = d; + nsXPTCVariant *l_s = s; + uint32_t l_paramCount = paramCount, fpCount = 0; + double *l_fprData = fprData; + + for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++) + { + if(l_s->IsPtrData()) + { + *l_d = (uint64_t)l_s->ptr; + continue; + } + switch(l_s->type) + { + case nsXPTType::T_I8: *l_d = (uint64_t)l_s->val.i8; break; + case nsXPTType::T_I16: *l_d = (uint64_t)l_s->val.i16; break; + case nsXPTType::T_I32: *l_d = (uint64_t)l_s->val.i32; break; + case nsXPTType::T_I64: *l_d = (uint64_t)l_s->val.i64; break; + case nsXPTType::T_U8: *l_d = (uint64_t)l_s->val.u8; break; + case nsXPTType::T_U16: *l_d = (uint64_t)l_s->val.u16; break; + case nsXPTType::T_U32: *l_d = (uint64_t)l_s->val.u32; break; + case nsXPTType::T_U64: *l_d = (uint64_t)l_s->val.u64; break; + case nsXPTType::T_BOOL: *l_d = (uint64_t)l_s->val.b; break; + case nsXPTType::T_CHAR: *l_d = (uint64_t)l_s->val.c; break; + case nsXPTType::T_WCHAR: *l_d = (uint64_t)l_s->val.wc; break; + + case nsXPTType::T_DOUBLE: + *((double*)l_d) = l_s->val.d; + if(fpCount < 13) + l_fprData[fpCount++] = l_s->val.d; + break; + case nsXPTType::T_FLOAT: + *((float*)l_d) = l_s->val.f; + if(fpCount < 13) + l_fprData[fpCount++] = l_s->val.f; + break; + default: + // all the others are plain pointer types + *l_d = (uint64_t)l_s->val.p; + break; + } + } +} +#endif diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp new file mode 100644 index 0000000000..6af3608357 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp @@ -0,0 +1,128 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Platform specific code to invoke XPCOM methods on native objects + +// The purpose of NS_InvokeByIndex() is to map a platform +// indepenpent call to the platform ABI. To do that, +// NS_InvokeByIndex() has to determine the method to call via vtable +// access. The parameters for the method are read from the +// nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC +// ABI this means that the first 8 integral and floating point +// parameters are passed in registers. + +#include "xptcprivate.h" + +// 8 integral parameters are passed in registers +#define GPR_COUNT 8 + +// With hardfloat support 8 floating point parameters are passed in registers, +// floats are promoted to doubles when passed in registers +// In Softfloat mode, everything is handled via gprs +#ifndef __NO_FPRS__ +#define FPR_COUNT 8 +#endif +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + return uint32_t(((paramCount * 2) + 3) & ~3); +} + +extern "C" void +invoke_copy_to_stack(uint32_t* d, + uint32_t paramCount, + nsXPTCVariant* s, + uint32_t* gpregs, + double* fpregs) +{ + uint32_t gpr = 1; // skip one GP reg for 'that' +#ifndef __NO_FPRS__ + uint32_t fpr = 0; +#endif + uint32_t tempu32; + uint64_t tempu64; + + for(uint32_t i = 0; i < paramCount; i++, s++) { + if(s->IsPtrData()) { + if(s->type == nsXPTType::T_JSVAL) + tempu32 = (uint32_t) &s->ptr; + else + tempu32 = (uint32_t) s->ptr; + } + else { + switch(s->type) { + case nsXPTType::T_FLOAT: break; + case nsXPTType::T_DOUBLE: break; + case nsXPTType::T_I8: tempu32 = s->val.i8; break; + case nsXPTType::T_I16: tempu32 = s->val.i16; break; + case nsXPTType::T_I32: tempu32 = s->val.i32; break; + case nsXPTType::T_I64: tempu64 = s->val.i64; break; + case nsXPTType::T_U8: tempu32 = s->val.u8; break; + case nsXPTType::T_U16: tempu32 = s->val.u16; break; + case nsXPTType::T_U32: tempu32 = s->val.u32; break; + case nsXPTType::T_U64: tempu64 = s->val.u64; break; + case nsXPTType::T_BOOL: tempu32 = s->val.b; break; + case nsXPTType::T_CHAR: tempu32 = s->val.c; break; + case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break; + default: tempu32 = (uint32_t) s->val.p; break; + } + } + + if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) { +#ifndef __NO_FPRS__ + if (fpr < FPR_COUNT) + fpregs[fpr++] = s->val.d; +#else + if (gpr & 1) + gpr++; + if ((gpr + 1) < GPR_COUNT) { + *((double*) &gpregs[gpr]) = s->val.d; + gpr += 2; + } +#endif + else { + if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack + *((double*) d) = s->val.d; + d += 2; + } + } + else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) { +#ifndef __NO_FPRS__ + if (fpr < FPR_COUNT) + fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles +#else + if (gpr < GPR_COUNT) + *((float*) &gpregs[gpr++]) = s->val.f; +#endif + else + *((float*) d++) = s->val.f; + } + else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64 + || s->type == nsXPTType::T_U64)) { + if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6 + if ((gpr + 1) < GPR_COUNT) { + *((uint64_t*) &gpregs[gpr]) = tempu64; + gpr += 2; + } + else { + if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack + *((uint64_t*) d) = tempu64; + d += 2; + } + } + else { + if (gpr < GPR_COUNT) + gpregs[gpr++] = tempu32; + else + *d++ = tempu32; + } + + } +} + +extern "C" +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp new file mode 100644 index 0000000000..5c4f8b49fe --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp @@ -0,0 +1,109 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Platform specific code to invoke XPCOM methods on native objects + +// The purpose of NS_InvokeByIndex() is to map a platform +// indepenpent call to the platform ABI. To do that, +// NS_InvokeByIndex() has to determine the method to call via vtable +// access. The parameters for the method are read from the +// nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC +// ABI this means that the first 8 integral and floating point +// parameters are passed in registers. + +#include "xptcprivate.h" + +// 8 integral parameters are passed in registers +#define GPR_COUNT 8 + +// 8 floating point parameters are passed in registers, floats are +// promoted to doubles when passed in registers +#define FPR_COUNT 8 + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + return uint32_t(((paramCount * 2) + 3) & ~3); +} + +extern "C" void +invoke_copy_to_stack(uint32_t* d, + uint32_t paramCount, + nsXPTCVariant* s, + uint32_t* gpregs, + double* fpregs) +{ + uint32_t gpr = 1; // skip one GP reg for 'that' + uint32_t fpr = 0; + uint32_t tempu32; + uint64_t tempu64; + + for(uint32_t i = 0; i < paramCount; i++, s++) { + if(s->IsPtrData()) { + if(s->type == nsXPTType::T_JSVAL) + tempu32 = (uint32_t) &(s->ptr); + else + tempu32 = (uint32_t) s->ptr; + } else { + switch(s->type) { + case nsXPTType::T_FLOAT: break; + case nsXPTType::T_DOUBLE: break; + case nsXPTType::T_I8: tempu32 = s->val.i8; break; + case nsXPTType::T_I16: tempu32 = s->val.i16; break; + case nsXPTType::T_I32: tempu32 = s->val.i32; break; + case nsXPTType::T_I64: tempu64 = s->val.i64; break; + case nsXPTType::T_U8: tempu32 = s->val.u8; break; + case nsXPTType::T_U16: tempu32 = s->val.u16; break; + case nsXPTType::T_U32: tempu32 = s->val.u32; break; + case nsXPTType::T_U64: tempu64 = s->val.u64; break; + case nsXPTType::T_BOOL: tempu32 = s->val.b; break; + case nsXPTType::T_CHAR: tempu32 = s->val.c; break; + case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break; + default: tempu32 = (uint32_t) s->val.p; break; + } + } + + if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) { + if (fpr < FPR_COUNT) + fpregs[fpr++] = s->val.d; + else { + if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack + *((double*) d) = s->val.d; + d += 2; + } + } + else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) { + if (fpr < FPR_COUNT) + fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles + else + *((float*) d++) = s->val.f; + } + else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64 + || s->type == nsXPTType::T_U64)) { + if ((gpr + 1) < GPR_COUNT) { + if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6 + *((uint64_t*) &gpregs[gpr]) = tempu64; + gpr += 2; + } + else { + if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack + *((uint64_t*) d) = tempu64; + d += 2; + } + } + else { + if (gpr < GPR_COUNT) + gpregs[gpr++] = tempu32; + else + *d++ = tempu32; + } + + } +} + +extern "C" +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp new file mode 100644 index 0000000000..4a434c426b --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp @@ -0,0 +1,113 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t result = 0; + /* fprintf(stderr,"invoke_count_words(%d,%p)\n",paramCount, s);*/ + + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + return result; +} + +extern "C" void +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s, double *fprData) +{ + uint32_t fpCount = 0; + + /* fprintf(stderr,"invoke_copy_to_stack(%p, %d, %p, %p)\n", d, paramCount, s, fprData);*/ + + for(uint32_t i = 0; i < paramCount; i++, d++, s++) + { + if(s->IsPtrData()) + { + *((void**)d) = s->ptr; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : *((int32_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U8 : *((uint32_t*) d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; + if (fpCount < 13) + fprData[fpCount++] = s->val.f; + break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; + if (fpCount < 13) + fprData[fpCount++] = s->val.d; + break; + case nsXPTType::T_BOOL : *((uint32_t*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((int32_t*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((uint32_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} + +extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, + nsXPTCVariant* params); + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + return _NS_InvokeByIndex(that, methodIndex, paramCount, params); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_riscv64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_riscv64.cpp new file mode 100644 index 0000000000..ddd6692156 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_riscv64.cpp @@ -0,0 +1,106 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Platform specific code to invoke XPCOM methods on native objects + +#if defined(__riscv_float_abi_soft) +# error "Not support soft float ABI" +#endif + +#include "xptcprivate.h" + +extern "C" void invoke_copy_to_stack(uint64_t* gpregs, double* fpregs, + uint32_t paramCount, nsXPTCVariant* s, + uint64_t* d) { + static const uint32_t GPR_COUNT = 8; + static const uint32_t FPR_COUNT = 8; + + uint32_t nr_gpr = 1; // skip one GPR register for "this" + uint32_t nr_fpr = 0; + uint64_t value = 0; + + for (uint32_t i = 0; i < paramCount; i++, s++) { + if (s->IsIndirect()) { + value = (uint64_t)&s->val; + } else { + switch (s->type) { + case nsXPTType::T_FLOAT: + break; + case nsXPTType::T_DOUBLE: + break; + case nsXPTType::T_I8: + value = s->val.i8; + break; + case nsXPTType::T_I16: + value = s->val.i16; + break; + case nsXPTType::T_I32: + value = s->val.i32; + break; + case nsXPTType::T_I64: + value = s->val.i64; + break; + case nsXPTType::T_U8: + value = s->val.u8; + break; + case nsXPTType::T_U16: + value = s->val.u16; + break; + case nsXPTType::T_U32: + value = s->val.u32; + break; + case nsXPTType::T_U64: + value = s->val.u64; + break; + case nsXPTType::T_BOOL: + value = s->val.b; + break; + case nsXPTType::T_CHAR: + value = s->val.c; + break; + case nsXPTType::T_WCHAR: + value = s->val.wc; + break; + default: + value = (uint64_t)s->val.p; + break; + } + } + + if (!s->IsIndirect() && s->type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) { + fpregs[nr_fpr++] = s->val.d; + } else { + *((double*)d) = s->val.d; + d++; + } + } else if (!s->IsIndirect() && s->type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) { + // The value in %fa register is already prepared to + // be retrieved as a float. Therefore, we pass the + // value verbatim, as a double without conversion. + fpregs[nr_fpr++] = s->val.d; + } else { + *((float*)d) = s->val.f; + d++; + } + } else { + if (nr_gpr < GPR_COUNT) { + gpregs[nr_gpr++] = value; + } else { + *d++ = value; + } + } + } +} + +extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, + nsXPTCVariant* params); + +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, uint32_t paramCount, + nsXPTCVariant* params) { + return _NS_InvokeByIndex(that, methodIndex, paramCount, params); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp new file mode 100644 index 0000000000..aa90988a17 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#if !defined(__sparc) && !defined(__sparc__) +#error "This code is for Sparc only" +#endif + +extern "C" uint64_t +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + /* + We need to copy the parameters for this function to locals and use them + from there since the parameters occupy the same stack space as the stack + we're trying to populate. + */ + uint64_t *l_d = d; + nsXPTCVariant *l_s = s; + uint64_t l_paramCount = paramCount; + uint64_t regCount = 0; // return the number of registers to load from the stack + + for(uint64_t i = 0; i < l_paramCount; i++, l_d++, l_s++) + { + if (regCount < 5) regCount++; + + if (l_s->IsIndirect()) + { + *l_d = (uint64_t) &l_s->val; + continue; + } + switch (l_s->type) + { + case nsXPTType::T_I8 : *((int64_t*)l_d) = l_s->val.i8; break; + case nsXPTType::T_I16 : *((int64_t*)l_d) = l_s->val.i16; break; + case nsXPTType::T_I32 : *((int64_t*)l_d) = l_s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*)l_d) = l_s->val.i64; break; + + case nsXPTType::T_U8 : *((uint64_t*)l_d) = l_s->val.u8; break; + case nsXPTType::T_U16 : *((uint64_t*)l_d) = l_s->val.u16; break; + case nsXPTType::T_U32 : *((uint64_t*)l_d) = l_s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)l_d) = l_s->val.u64; break; + + /* in the case of floats, we want to put the bits in to the + 64bit space right justified... floats in the parameter array on + sparcv9 use odd numbered registers.. %f1, %f3, so we have to skip + the space that would be occupied by %f0, %f2, etc. + */ + case nsXPTType::T_FLOAT : *(((float*)l_d) + 1) = l_s->val.f; break; + case nsXPTType::T_DOUBLE: *((double*)l_d) = l_s->val.d; break; + case nsXPTType::T_BOOL : *((int64_t*)l_d) = l_s->val.b; break; + case nsXPTType::T_CHAR : *((uint64_t*)l_d) = l_s->val.c; break; + case nsXPTType::T_WCHAR : *((int64_t*)l_d) = l_s->val.wc; break; + + default: + // all the others are plain pointer types + *((void**)l_d) = l_s->val.p; + break; + } + } + + return regCount; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp new file mode 100644 index 0000000000..3ab0812622 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp @@ -0,0 +1,130 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +/* solaris defines __sparc for workshop compilers and + linux defines __sparc__ */ + +#if !defined(__sparc) && !defined(__sparc__) +#error "This code is for Sparc only" +#endif + +typedef unsigned nsXPCVariant; + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t result = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + // nuts, I know there's a cooler way of doing this, but it's late + // now and it'll probably come to me in the morning. + if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment + return result; +} + +extern "C" uint32_t +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ +/* + We need to copy the parameters for this function to locals and use them + from there since the parameters occupy the same stack space as the stack + we're trying to populate. +*/ + uint32_t *l_d = d; + nsXPTCVariant *l_s = s; + uint32_t l_paramCount = paramCount; + uint32_t regCount = 0; // return the number of registers to load from the stack + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + + for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++) + { + if (regCount < 5) regCount++; + if(l_s->IsPtrData()) + { + if(l_s->type == nsXPTType::T_JSVAL) + { + // On SPARC, we need to pass a pointer to HandleValue + *((void**)l_d) = &l_s->ptr; + } else + { + *((void**)l_d) = l_s->ptr; + } + continue; + } + switch(l_s->type) + { + case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break; + case nsXPTType::T_I64 : + case nsXPTType::T_U64 : + case nsXPTType::T_DOUBLE : *((uint32_t*) l_d++) = ((DU *)l_s)->hi; + if (regCount < 5) regCount++; + *((uint32_t*) l_d) = ((DU *)l_s)->lo; + break; + case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break; + case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break; + case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break; + case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break; + case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)l_d) = l_s->val.p; + break; + } + } + return regCount; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp new file mode 100644 index 0000000000..fb99c303f7 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp @@ -0,0 +1,127 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#if !defined(__sparc__) +#error "This code is for Sparc only" +#endif + +typedef unsigned nsXPCVariant; + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t result = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + // nuts, I know there's a cooler way of doing this, but it's late + // now and it'll probably come to me in the morning. + if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment + return result; +} + +extern "C" uint32_t +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ +/* + We need to copy the parameters for this function to locals and use them + from there since the parameters occupy the same stack space as the stack + we're trying to populate. +*/ + uint32_t *l_d = d; + nsXPTCVariant *l_s = s; + uint32_t l_paramCount = paramCount; + uint32_t regCount = 0; // return the number of registers to load from the stack + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + + for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++) + { + if (regCount < 5) regCount++; + if(l_s->IsPtrData()) + { + if(l_s->type == nsXPTType::T_JSVAL) + { + // On SPARC, we need to pass a pointer to HandleValue + *((void**)l_d) = &l_s->ptr; + } else + { + *((void**)l_d) = l_s->ptr; + } + continue; + } + switch(l_s->type) + { + case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break; + case nsXPTType::T_I64 : + case nsXPTType::T_U64 : + case nsXPTType::T_DOUBLE : *((uint32_t*) l_d++) = ((DU *)l_s)->hi; + if (regCount < 5) regCount++; + *((uint32_t*) l_d) = ((DU *)l_s)->lo; + break; + case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break; + case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break; + case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break; + case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break; + case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)l_d) = l_s->val.p; + break; + } + } + return regCount; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp new file mode 100644 index 0000000000..3ab0812622 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp @@ -0,0 +1,130 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +/* solaris defines __sparc for workshop compilers and + linux defines __sparc__ */ + +#if !defined(__sparc) && !defined(__sparc__) +#error "This code is for Sparc only" +#endif + +typedef unsigned nsXPCVariant; + +extern "C" uint32_t +invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) +{ + uint32_t result = 0; + for(uint32_t i = 0; i < paramCount; i++, s++) + { + if(s->IsPtrData()) + { + result++; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : + case nsXPTType::T_I16 : + case nsXPTType::T_I32 : + result++; + break; + case nsXPTType::T_I64 : + result+=2; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=2; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=2; + break; + case nsXPTType::T_BOOL : + case nsXPTType::T_CHAR : + case nsXPTType::T_WCHAR : + result++; + break; + default: + // all the others are plain pointer types + result++; + break; + } + } + // nuts, I know there's a cooler way of doing this, but it's late + // now and it'll probably come to me in the morning. + if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment + return result; +} + +extern "C" uint32_t +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ +/* + We need to copy the parameters for this function to locals and use them + from there since the parameters occupy the same stack space as the stack + we're trying to populate. +*/ + uint32_t *l_d = d; + nsXPTCVariant *l_s = s; + uint32_t l_paramCount = paramCount; + uint32_t regCount = 0; // return the number of registers to load from the stack + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + + for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++) + { + if (regCount < 5) regCount++; + if(l_s->IsPtrData()) + { + if(l_s->type == nsXPTType::T_JSVAL) + { + // On SPARC, we need to pass a pointer to HandleValue + *((void**)l_d) = &l_s->ptr; + } else + { + *((void**)l_d) = l_s->ptr; + } + continue; + } + switch(l_s->type) + { + case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break; + case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break; + case nsXPTType::T_I64 : + case nsXPTType::T_U64 : + case nsXPTType::T_DOUBLE : *((uint32_t*) l_d++) = ((DU *)l_s)->hi; + if (regCount < 5) regCount++; + *((uint32_t*) l_d) = ((DU *)l_s)->lo; + break; + case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break; + case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break; + case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break; + case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break; + case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break; + case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)l_d) = l_s->val.p; + break; + } + } + return regCount; +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp new file mode 100644 index 0000000000..ae034abf29 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp @@ -0,0 +1,76 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Platform specific code to invoke XPCOM methods on native objects + +#include "xptcall.h" +#include "xptinfo.h" + +// 6 integral parameters are passed in registers, but 1 is |this| which isn't +// considered here. +const uint32_t GPR_COUNT = 5; + +// 8 floating point parameters are passed in SSE registers +const uint32_t FPR_COUNT = 8; + +extern "C" void +InvokeCopyToStack(uint64_t * gpregs, double * fpregs, + uint32_t paramCount, nsXPTCVariant * s, + uint64_t* d) +{ + uint32_t nr_gpr = 0u; + uint32_t nr_fpr = 0u; + uint64_t value = 0u; + + for (uint32_t i = 0; i < paramCount; i++, s++) { + if (s->IsIndirect()) + value = (uint64_t) &s->val; + else { + switch (s->type) { + case nsXPTType::T_FLOAT: break; + case nsXPTType::T_DOUBLE: break; + case nsXPTType::T_I8: value = s->val.i8; break; + case nsXPTType::T_I16: value = s->val.i16; break; + case nsXPTType::T_I32: value = s->val.i32; break; + case nsXPTType::T_I64: value = s->val.i64; break; + case nsXPTType::T_U8: value = s->val.u8; break; + case nsXPTType::T_U16: value = s->val.u16; break; + case nsXPTType::T_U32: value = s->val.u32; break; + case nsXPTType::T_U64: value = s->val.u64; break; + case nsXPTType::T_BOOL: value = s->val.b; break; + case nsXPTType::T_CHAR: value = s->val.c; break; + case nsXPTType::T_WCHAR: value = s->val.wc; break; + default: value = (uint64_t) s->val.p; break; + } + } + + if (!s->IsIndirect() && s->type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) + fpregs[nr_fpr++] = s->val.d; + else { + *((double *)d) = s->val.d; + d++; + } + } + else if (!s->IsIndirect() && s->type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) + // The value in %xmm register is already prepared to + // be retrieved as a float. Therefore, we pass the + // value verbatim, as a double without conversion. + fpregs[nr_fpr++] = s->val.d; + else { + *((float *)d) = s->val.f; + d++; + } + } + else { + if (nr_gpr < GPR_COUNT) + gpregs[nr_gpr++] = value; + else + *d++ = value; + } + } +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp new file mode 100644 index 0000000000..d535557259 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp @@ -0,0 +1,238 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" + +#ifndef __AARCH64EL__ +#error "Only little endian compatibility was tested" +#endif + +template<typename T> void +get_value_and_advance(T* aOutValue, void*& aStack) { +#ifdef __APPLE__ + const size_t aligned_size = sizeof(T); +#else + const size_t aligned_size = 8; +#endif + // Ensure the pointer is aligned for the type + uintptr_t addr = (reinterpret_cast<uintptr_t>(aStack) + aligned_size - 1) & ~(aligned_size - 1); + memcpy(aOutValue, reinterpret_cast<void*>(addr), sizeof(T)); + aStack = reinterpret_cast<void*>(addr + aligned_size); +} + +/* + * This is for AArch64 ABI + * + * When we're called, the "gp" registers are stored in gprData and + * the "fp" registers are stored in fprData. Each array has 8 regs + * but first reg in gprData is a placeholder for 'self'. + */ +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, void* args, + uint64_t *gprData, double *fprData) +{ +#define PARAM_GPR_COUNT 8 +#define PARAM_FPR_COUNT 8 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + uint32_t paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + void* ap = args; + uint32_t next_gpr = 1; // skip first arg which is 'self' + uint32_t next_fpr = 0; + for (uint32_t i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (next_gpr < PARAM_GPR_COUNT) + next_gpr++; + else { + void* value; + get_value_and_advance(&value, ap); + } + } + + if (param.IsOut() || !type.IsArithmetic()) { + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.p = (void*)gprData[next_gpr++]; + } else { + get_value_and_advance(&dp->val.p, ap); + } + continue; + } + + switch (type) { + case nsXPTType::T_I8: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.i8 = (int8_t)gprData[next_gpr++]; + } else { + get_value_and_advance(&dp->val.i8, ap); + } + break; + + case nsXPTType::T_I16: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.i16 = (int16_t)gprData[next_gpr++]; + } else { + get_value_and_advance(&dp->val.i16, ap); + } + break; + + case nsXPTType::T_I32: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.i32 = (int32_t)gprData[next_gpr++]; + } else { + get_value_and_advance(&dp->val.i32, ap); + } + break; + + case nsXPTType::T_I64: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.i64 = (int64_t)gprData[next_gpr++]; + } else { + get_value_and_advance(&dp->val.i64, ap); + } + break; + + case nsXPTType::T_U8: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.u8 = (uint8_t)gprData[next_gpr++]; + } else { + get_value_and_advance(&dp->val.u8, ap); + } + break; + + case nsXPTType::T_U16: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.u16 = (uint16_t)gprData[next_gpr++]; + } else { + get_value_and_advance(&dp->val.u16, ap); + } + break; + + case nsXPTType::T_U32: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.u32 = (uint32_t)gprData[next_gpr++]; + } else { + get_value_and_advance(&dp->val.u32, ap); + } + break; + + case nsXPTType::T_U64: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.u64 = (uint64_t)gprData[next_gpr++]; + } else { + get_value_and_advance(&dp->val.u64, ap); + } + break; + + case nsXPTType::T_FLOAT: + if (next_fpr < PARAM_FPR_COUNT) { + memcpy(&dp->val.f, &fprData[next_fpr++], sizeof(dp->val.f)); + } else { + get_value_and_advance(&dp->val.f, ap); + } + break; + + case nsXPTType::T_DOUBLE: + if (next_fpr < PARAM_FPR_COUNT) { + memcpy(&dp->val.d, &fprData[next_fpr++], sizeof(dp->val.d)); + } else { + get_value_and_advance(&dp->val.d, ap); + } + break; + + case nsXPTType::T_BOOL: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.b = (bool)(uint8_t)gprData[next_gpr++]; + } else { + uint8_t value; + get_value_and_advance(&value, ap); + dp->val.b = (bool)value; + } + break; + + case nsXPTType::T_CHAR: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.c = (char)gprData[next_gpr++]; + } else { + get_value_and_advance(&dp->val.c, ap); + } + break; + + case nsXPTType::T_WCHAR: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.wc = (wchar_t)gprData[next_gpr++]; + } else { + get_value_and_advance(&dp->val.wc, ap); + } + break; + + default: + NS_ASSERTION(0, "bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +#ifdef __APPLE__ +#define GNU(str) +#define UNDERSCORE "__" +#else +#define GNU(str) str +#define UNDERSCORE "_" +#endif + +// Load w17 with the constant 'n' and branch to SharedStub(). +# define STUB_ENTRY(n) \ + __asm__ ( \ + ".text\n\t" \ + ".align 2\n\t" \ + ".if "#n" < 10 \n\t" \ + ".globl " UNDERSCORE "ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + GNU(".hidden _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t") \ + GNU(".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n")\ + "" UNDERSCORE "ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + ".elseif "#n" < 100 \n\t" \ + ".globl " UNDERSCORE "ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + GNU(".hidden _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t") \ + GNU(".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n")\ + "" UNDERSCORE "ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + ".elseif "#n" < 1000 \n\t" \ + ".globl " UNDERSCORE "ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + GNU(".hidden _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t") \ + GNU(".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n")\ + UNDERSCORE "ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + ".else \n\t" \ + ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ + ".endif \n\t" \ + "mov w17,#"#n" \n\t" \ + "b SharedStub \n" \ +); + +#define SENTINEL_ENTRY(n) \ + nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp new file mode 100644 index 0000000000..248c658d68 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp @@ -0,0 +1,178 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +/* Prototype specifies unmangled function name and disables unused warning */ +static nsresult +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args) +__asm__("PrepareAndDispatch") ATTRIBUTE_USED; + +static nsresult +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args) +{ + const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + // args[0] to args[NUM_ARG_REGS] hold floating point register values + uint64_t* ap = args + NUM_ARG_REGS; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) + ap++; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = (int8_t) *ap; break; + case nsXPTType::T_I16 : dp->val.i16 = (int16_t) *ap; break; + case nsXPTType::T_I32 : dp->val.i32 = (int32_t) *ap; break; + case nsXPTType::T_I64 : dp->val.i64 = (int64_t) *ap; break; + case nsXPTType::T_U8 : dp->val.u8 = (uint8_t) *ap; break; + case nsXPTType::T_U16 : dp->val.u16 = (uint16_t) *ap; break; + case nsXPTType::T_U32 : dp->val.u32 = (uint32_t) *ap; break; + case nsXPTType::T_U64 : dp->val.u64 = (uint64_t) *ap; break; + case nsXPTType::T_FLOAT : + if(i < NUM_ARG_REGS) + { + // floats passed via registers are stored as doubles + // in the first NUM_ARG_REGS entries in args + dp->val.u64 = (uint64_t) args[i]; + dp->val.f = (float) dp->val.d; // convert double to float + } + else + dp->val.u32 = (uint32_t) *ap; + break; + case nsXPTType::T_DOUBLE : + // doubles passed via registers are also stored + // in the first NUM_ARG_REGS entries in args + dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap; + break; + case nsXPTType::T_BOOL : dp->val.b = (bool) *ap; break; + case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break; + case nsXPTType::T_WCHAR : dp->val.wc = (char16_t) *ap; break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +/* + * SharedStub() + * Collects arguments and calls PrepareAndDispatch. The "methodIndex" is + * passed to this function via $1 to preserve the argument registers. + */ +__asm__( + "#### SharedStub ####\n" +".text\n\t" + ".align 5\n\t" + ".ent SharedStub\n" +"SharedStub:\n\t" + ".frame $30,96,$26,0\n\t" + ".mask 0x4000000,-96\n\t" + "ldgp $29,0($27)\n" +"$SharedStub..ng:\n\t" + "subq $30,96,$30\n\t" + "stq $26,0($30)\n\t" + ".prologue 1\n\t" + + /* + * Store arguments passed via registers to the stack. + * Floating point registers are stored as doubles and converted + * to floats in PrepareAndDispatch if necessary. + */ + "stt $f17,16($30)\n\t" /* floating point registers */ + "stt $f18,24($30)\n\t" + "stt $f19,32($30)\n\t" + "stt $f20,40($30)\n\t" + "stt $f21,48($30)\n\t" + "stq $17,56($30)\n\t" /* integer registers */ + "stq $18,64($30)\n\t" + "stq $19,72($30)\n\t" + "stq $20,80($30)\n\t" + "stq $21,88($30)\n\t" + + /* + * Call PrepareAndDispatch function. + */ + "bis $1,$1,$17\n\t" /* pass "methodIndex" */ + "addq $30,16,$18\n\t" /* pass "args" */ + "bsr $26,$PrepareAndDispatch..ng\n\t" + + "ldq $26,0($30)\n\t" + "addq $30,96,$30\n\t" + "ret $31,($26),1\n\t" + ".end SharedStub" + ); + +/* + * nsresult nsXPTCStubBase::Stub##n() + * Sets register $1 to "methodIndex" and jumps to SharedStub. + */ +#define STUB_MANGLED_ENTRY(n, symbol) \ + "#### Stub"#n" ####" "\n\t" \ + ".text" "\n\t" \ + ".align 5" "\n\t" \ + ".globl " symbol "\n\t" \ + ".ent " symbol "\n" \ +symbol ":" "\n\t" \ + ".frame $30,0,$26,0" "\n\t" \ + "ldgp $29,0($27)" "\n" \ +"$" symbol "..ng:" "\n\t" \ + ".prologue 1" "\n\t" \ + "lda $1,"#n "\n\t" \ + "br $31,$SharedStub..ng" "\n\t" \ + ".end " symbol + +#define STUB_ENTRY(n) \ +__asm__( \ + ".if "#n" < 10" "\n\t" \ + STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase5Stub"#n"Ev") "\n\t" \ + ".elseif "#n" < 100" "\n\t" \ + STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase6Stub"#n"Ev") "\n\t" \ + ".elseif "#n" < 1000" "\n\t" \ + STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase7Stub"#n"Ev") "\n\t" \ + ".else" "\n\t" \ + ".err \"Stub"#n" >= 1000 not yet supported.\"" "\n\t" \ + ".endif" \ + ); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp new file mode 100644 index 0000000000..da855b7535 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp @@ -0,0 +1,226 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +#if !defined(__arm__) && !(defined(LINUX) || defined(ANDROID) || defined(XP_DARWIN)) +#error "This code is for Linux/iOS ARM only. Please check if it works for you, too.\nDepends strongly on gcc behaviour." +#endif + +#ifdef __ARM_EABI__ +#define DOUBLEWORD_ALIGN(p) ((uint32_t *)((((uint32_t)(p)) + 7) & 0xfffffff8)) +#else +#define DOUBLEWORD_ALIGN(p) (p) +#endif + +// Apple's iOS toolchain is lame. +#ifdef __APPLE__ +#define GNU(str) +#define APPLE(str) str +#define UNDERSCORE "__" +#else +#define GNU(str) str +#define APPLE(str) +#define UNDERSCORE "_" +#endif + +#ifdef __thumb__ +#define THUMB_FUNC ".thumb_func\n" +#else +#define THUMB_FUNC +#endif + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) + ap++; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_I64 : ap = DOUBLEWORD_ALIGN(ap); + dp->val.i64 = *((int64_t*) ap); ap++; break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_U64 : ap = DOUBLEWORD_ALIGN(ap); + dp->val.u64 = *((uint64_t*)ap); ap++; break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_DOUBLE : ap = DOUBLEWORD_ALIGN(ap); + dp->val.d = *((double*) ap); ap++; break; + case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +/* + * This is our shared stub. + * + * r0 = Self. + * + * The Rules: + * We pass an (undefined) number of arguments into this function. + * The first 3 C++ arguments are in r1 - r3, the rest are built + * by the calling function on the stack. + * + * We are allowed to corrupt r0 - r3, ip, and lr. + * + * Other Info: + * We pass the stub number in using `ip'. + * + * Implementation: + * - We save r1 to r3 inclusive onto the stack, which will be + * immediately below the caller saved arguments. + * - setup r2 (PrepareAndDispatch's args pointer) to point at + * the base of all these arguments + * - Save LR (for the return address) + * - Set r1 (PrepareAndDispatch's methodindex argument) from ip + * - r0 is passed through (self) + * - Call PrepareAndDispatch + * - When the call returns, we return by loading the PC off the + * stack, and undoing the stack (one instruction)! + * + */ +__asm__ ("\n" + GNU(".text\n") + APPLE(".section __TEXT,__text\n") + THUMB_FUNC + ".align 2\n" + "SharedStub:\n" + GNU(".fnstart\n") + GNU(".cfi_startproc\n") + "stmfd sp!, {r1, r2, r3}\n" + GNU(".save {r1, r2, r3}\n") + GNU(".cfi_def_cfa_offset 12\n") + GNU(".cfi_offset r3, -4\n") + GNU(".cfi_offset r2, -8\n") + GNU(".cfi_offset r1, -12\n") + "mov r2, sp\n" + "str lr, [sp, #-4]!\n" + GNU(".save {lr}\n") + GNU(".cfi_def_cfa_offset 16\n") + GNU(".cfi_offset lr, -16\n") + "mov r1, ip\n" + "bl PrepareAndDispatch\n" + "ldr pc, [sp], #16\n" + GNU(".cfi_endproc\n") + GNU(".fnend")); + +/* + * Create sets of stubs to call the SharedStub. + * We don't touch the stack here, nor any registers, other than IP. + * IP is defined to be corruptable by a called function, so we are + * safe to use it. + * + * This will work with or without optimisation. + */ + +/* + * Note : As G++3 ABI contains the length of the functionname in the + * mangled name, it is difficult to get a generic assembler mechanism like + * in the G++ 2.95 case. + * Create names would be like : + * _ZN14nsXPTCStubBase5Stub9Ev + * _ZN14nsXPTCStubBase6Stub13Ev + * _ZN14nsXPTCStubBase7Stub144Ev + * Use the assembler directives to get the names right... + */ + +#define STUB_ENTRY(n) \ + __asm__( \ + GNU(".section \".text\"\n") \ + APPLE(".section __TEXT,__text\n") \ +" .align 2\n" \ +" .if ("#n" - 10) < 0\n" \ +" .globl " UNDERSCORE "ZN14nsXPTCStubBase5Stub"#n"Ev\n" \ + THUMB_FUNC \ + GNU(".type _ZN14nsXPTCStubBase5Stub"#n"Ev,#function\n") \ +UNDERSCORE "ZN14nsXPTCStubBase5Stub"#n"Ev:\n" \ +" .else\n" \ +" .if ("#n" - 100) < 0\n" \ +" .globl " UNDERSCORE "ZN14nsXPTCStubBase6Stub"#n"Ev\n" \ + THUMB_FUNC \ + GNU(".type _ZN14nsXPTCStubBase6Stub"#n"Ev,#function\n") \ +UNDERSCORE "ZN14nsXPTCStubBase6Stub"#n"Ev:\n" \ +" .else\n" \ +" .if ("#n" - 1000) < 0\n" \ +" .globl " UNDERSCORE "ZN14nsXPTCStubBase7Stub"#n"Ev\n" \ + THUMB_FUNC \ + GNU(".type _ZN14nsXPTCStubBase7Stub"#n"Ev,#function\n") \ +UNDERSCORE "ZN14nsXPTCStubBase7Stub"#n"Ev:\n" \ +" .else\n" \ +" .err \"stub number "#n"> 1000 not yet supported\"\n" \ +" .endif\n" \ +" .endif\n" \ +" .endif\n" \ +" mov ip, #"#n"\n" \ +" b SharedStub\n\t"); + +#if 0 +/* + * This part is left in as comment : this is how the method definition + * should look like. + */ + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n () \ +{ \ + __asm__ ( \ +" mov ip, #"#n"\n" \ +" b SharedStub\n\t"); \ + return 0; /* avoid warnings */ \ +} +#endif + + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp new file mode 100644 index 0000000000..be7a36e948 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp @@ -0,0 +1,99 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTInterfaceInfo* iface_info = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->GetInterfaceInfo(&iface_info); + NS_ASSERTION(iface_info,"no interface info"); + + iface_info->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break; + case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +/* + * These stubs move just move the values passed in registers onto the stack, + * so they are contiguous with values passed on the stack, and then calls + * PrepareAndDispatch() to do the dirty work. + */ + +#define STUB_ENTRY(n) \ +__asm__( \ + ".global _Stub"#n"__14nsXPTCStubBase\n\t" \ +"_Stub"#n"__14nsXPTCStubBase:\n\t" \ + "stmfd sp!, {r1, r2, r3} \n\t" \ + "mov ip, sp \n\t" \ + "stmfd sp!, {fp, ip, lr, pc} \n\t" \ + "sub fp, ip, #4 \n\t" \ + "mov r1, #"#n" \n\t" /* = methodIndex */ \ + "add r2, sp, #16 \n\t" \ + "bl _PrepareAndDispatch__FP14nsXPTCStubBaseUiPUi \n\t" \ + "ldmea fp, {fp, sp, lr} \n\t" \ + "add sp, sp, #12 \n\t" \ + "mov pc, lr \n\t" \ +); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp new file mode 100644 index 0000000000..c0fb0df7d4 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp @@ -0,0 +1,194 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +#ifdef __GNUC__ +/* This tells gcc3.4+ not to optimize away symbols. + * @see http://gcc.gnu.org/gcc-3.4/changes.html + */ +#define DONT_DROP_OR_WARN __attribute__((used)) +#else +/* This tells older gccs not to warn about unused vairables. + * @see http://docs.freebsd.org/info/gcc/gcc.info.Variable_Attributes.html + */ +#define DONT_DROP_OR_WARN __attribute__((unused)) +#endif + +/* Specify explicitly a symbol for this function, don't try to guess the c++ mangled symbol. */ +static nsresult PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) asm("_PrepareAndDispatch") +DONT_DROP_OR_WARN; + +static nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) + ap++; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break; + case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +/* + * This is our shared stub. + * + * r0 = Self. + * + * The Rules: + * We pass an (undefined) number of arguments into this function. + * The first 3 C++ arguments are in r1 - r3, the rest are built + * by the calling function on the stack. + * + * We are allowed to corrupt r0 - r3, ip, and lr. + * + * Other Info: + * We pass the stub number in using `ip'. + * + * Implementation: + * - We save r1 to r3 inclusive onto the stack, which will be + * immediately below the caller saved arguments. + * - setup r2 (PrepareAndDispatch's args pointer) to point at + * the base of all these arguments + * - Save LR (for the return address) + * - Set r1 (PrepareAndDispatch's methodindex argument) from ip + * - r0 is passed through (self) + * - Call PrepareAndDispatch + * - When the call returns, we return by loading the PC off the + * stack, and undoing the stack (one instruction)! + * + */ +__asm__ ("\n\ + .text \n\ + .align 2 \n\ +SharedStub: \n\ + stmfd sp!, {r1, r2, r3} \n\ + mov r2, sp \n\ + str lr, [sp, #-4]! \n\ + mov r1, ip \n\ + bl _PrepareAndDispatch \n\ + ldr pc, [sp], #16"); + +/* + * Create sets of stubs to call the SharedStub. + * We don't touch the stack here, nor any registers, other than IP. + * IP is defined to be corruptable by a called function, so we are + * safe to use it. + * + * This will work with or without optimisation. + */ + +/* + * Note : As G++3 ABI contains the length of the functionname in the + * mangled name, it is difficult to get a generic assembler mechanism like + * in the G++ 2.95 case. + * Create names would be like : + * _ZN14nsXPTCStubBase5Stub9Ev + * _ZN14nsXPTCStubBase6Stub13Ev + * _ZN14nsXPTCStubBase7Stub144Ev + * Use the assembler directives to get the names right... + */ + +#define STUB_ENTRY(n) \ + __asm__( \ + ".section \".text\"\n" \ +" .align 2\n" \ +" .iflt ("#n" - 10)\n" \ +" .globl _ZN14nsXPTCStubBase5Stub"#n"Ev\n" \ +" .type _ZN14nsXPTCStubBase5Stub"#n"Ev,#function\n" \ +"_ZN14nsXPTCStubBase5Stub"#n"Ev:\n" \ +" .else\n" \ +" .iflt ("#n" - 100)\n" \ +" .globl _ZN14nsXPTCStubBase6Stub"#n"Ev\n" \ +" .type _ZN14nsXPTCStubBase6Stub"#n"Ev,#function\n" \ +"_ZN14nsXPTCStubBase6Stub"#n"Ev:\n" \ +" .else\n" \ +" .iflt ("#n" - 1000)\n" \ +" .globl _ZN14nsXPTCStubBase7Stub"#n"Ev\n" \ +" .type _ZN14nsXPTCStubBase7Stub"#n"Ev,#function\n" \ +"_ZN14nsXPTCStubBase7Stub"#n"Ev:\n" \ +" .else\n" \ +" .err \"stub number "#n"> 1000 not yet supported\"\n" \ +" .endif\n" \ +" .endif\n" \ +" .endif\n" \ +" mov ip, #"#n"\n" \ +" b SharedStub\n\t"); + +#if 0 +/* + * This part is left in as comment : this is how the method definition + * should look like. + */ + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n () \ +{ \ + __asm__ ( \ +" mov ip, #"#n"\n" \ +" b SharedStub\n\t"); \ + return 0; /* avoid warnings */ \ +} +#endif + + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.S new file mode 100644 index 0000000000..f2394aa316 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.S @@ -0,0 +1,62 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifdef __APPLE__ +#define SYM(x) _ ## x +#else +#define SYM(x) x +#endif + + .set NGPREGS,8 + .set NFPREGS,8 + + .text + .align 2 + .globl SharedStub +#ifndef __APPLE__ + .hidden SharedStub + .type SharedStub,@function +#endif +SharedStub: + .cfi_startproc + stp x29, x30, [sp,#-16]! + .cfi_adjust_cfa_offset 16 + .cfi_rel_offset x29, 0 + .cfi_rel_offset x30, 8 + mov x29, sp + .cfi_def_cfa_register x29 + + sub sp, sp, #8*(NGPREGS+NFPREGS) + stp x0, x1, [sp, #64+(0*8)] + stp x2, x3, [sp, #64+(2*8)] + stp x4, x5, [sp, #64+(4*8)] + stp x6, x7, [sp, #64+(6*8)] + stp d0, d1, [sp, #(0*8)] + stp d2, d3, [sp, #(2*8)] + stp d4, d5, [sp, #(4*8)] + stp d6, d7, [sp, #(6*8)] + + # methodIndex passed from stub + mov w1, w17 + + add x2, sp, #16+(8*(NGPREGS+NFPREGS)) + add x3, sp, #8*NFPREGS + add x4, sp, #0 + + bl SYM(PrepareAndDispatch) + + add sp, sp, #8*(NGPREGS+NFPREGS) + .cfi_def_cfa_register sp + ldp x29, x30, [sp],#16 + .cfi_adjust_cfa_offset -16 + .cfi_restore x29 + .cfi_restore x30 + ret + .cfi_endproc + +#ifndef __APPLE__ + .size SharedStub, . - SharedStub + + .section .note.GNU-stack, "", @progbits +#endif diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s new file mode 100644 index 0000000000..720dd6cc71 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s @@ -0,0 +1,123 @@ + +// Select C numeric constant + .radix C + .psr abi32 + .psr msb +// Section has executable code + .section .text, "ax","progbits" +// procedure named 'SharedStub' + .proc SharedStub +// manual bundling + .explicit + + .global PrepareAndDispatch +// .exclass PrepareAndDispatch, @fullyvisible + .type PrepareAndDispatch,@function + +SharedStub:: +// 10 arguments, first 8 are the input arguments of previous +// function call. The 9th one is methodIndex and the 10th is the +// pointer to the remaining input arguments. The last two arguments +// are passed in memory. + .prologue + .save ar.pfs , r41 +// allocate 8 input args, 4 local args, and 5 output args + alloc r41 = ar.pfs, 8, 4, 5, 0 // M + .save rp, r40 + mov r40 = rp // I + addp4 out4 = 28, sp ;; // I + + .save ar.unat, r42 + mov r42 = ar.unat // M + .fframe 144 + add sp = -144, sp // A +// unwind table already knows gp, don't need to specify anything + add r43 = 0, gp ;; // A + +// We have possible 8 integer registers and 8 float registers that could +// be arguments. We also have a stack region from the previous +// stack frame that may hold some stack arguments. +// We need to write the integer registers to a memory region, write +// the float registers to a memory region (making sure we don't step +// on NAT while touching the registers). We also mark the memory +// address of the stack arguments. +// We then call PrepareAndDispatch() specifying the three memory +// region pointers. + + + .body + add out0 = 0, in0 // A move self ptr +// 144 bytes = 16 byte stack header + 64 byte int space + 64 byte float space +// methodIndex is at 144 + 16 bytes away from current sp +// (current frame + previous frame header) + ld4 out4 = [out4] // A restarg address + add r11 = 160, sp ;; // A address of methodIndex + + ld8 out1 = [r11] // M load methodIndex +// sp + 16 is the start of intargs + add out2 = 16, sp // A address of intargs +// the intargs take up 64 bytes, so sp + 16 + 64 is the start of floatargs + add out3 = 80, sp ;; // A address of floatargs + + add r11 = 0, out2 ;; // A + st8.spill [r11] = in1, 8 // M + add r10 = 0, out3 ;; // A + + st8.spill [r11] = in2, 8 ;; // M + st8.spill [r11] = in3, 8 // M + nop.i 0 ;; // I + + st8.spill [r11] = in4, 8 ;; // M + st8.spill [r11] = in5, 8 // M + nop.i 0 ;; // I + + st8.spill [r11] = in6, 8 ;; // M + st8.spill [r11] = in7 // M + fclass.nm p14,p15 = f8,@nat ;; // F + +(p14) stfd [r10] = f8, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 = f9,@nat ;; // F + +(p12) stfd [r10] = f9, 8 // M +(p13) add r10 = 8, r10 // A + fclass.nm p14,p15 =f10,@nat ;; // F + +(p14) stfd [r10] = f10, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 =f11,@nat ;; // F + +(p12) stfd [r10] = f11, 8 // M +(p13) add r10 = 8, r10 // A + fclass.nm p14,p15 =f12,@nat ;; // F + +(p14) stfd [r10] = f12, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 =f13,@nat ;; // F + +(p12) stfd [r10] = f13, 8 // M +(p13) add r10 = 8, r10 // A + fclass.nm p14,p15 =f14,@nat ;; // F + +(p14) stfd [r10] = f14, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 =f15,@nat ;; // F + +(p12) stfd [r10] = f15, 8 // M +(p13) add r10 = 8, r10 // A + +// branch to PrepareAndDispatch + br.call.dptk.few rp = PrepareAndDispatch ;; // B + +// epilog + mov ar.unat = r42 // M + mov ar.pfs = r41 // I + mov rp = r40 ;; // I + + add gp = 0, r43 // A + add sp = 144, sp // A + br.ret.dptk.few rp ;; // B + + .endp + + diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s new file mode 100644 index 0000000000..0b5816f1be --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s @@ -0,0 +1,124 @@ + +// Select C numeric constant + .radix C + .psr abi64 + .psr lsb +// Section has executable code + .section .text, "ax","progbits" +// procedure named 'SharedStub' + .proc SharedStub +// manual bundling + .explicit + + .global PrepareAndDispatch +// .exclass PrepareAndDispatch, @fullyvisible + .type PrepareAndDispatch,@function + +SharedStub:: +// 10 arguments, first 8 are the input arguments of previous +// function call. The 9th one is methodIndex and the 10th is the +// pointer to the remaining input arguments. The last two arguments +// are passed in memory. + .prologue + .save ar.pfs , r41 +// allocate 8 input args, 4 local args, and 5 output args + alloc r41 = ar.pfs, 8, 4, 5, 0 // M + .save rp, r40 + mov r40 = rp // I + add out4 = 24, sp ;; // I + + .save ar.unat, r42 + mov r42 = ar.unat // M + .fframe 144 + add sp = -144, sp // A +// unwind table already knows gp, don't need to specify anything + add r43 = 0, gp ;; // A + +// We have possible 8 integer registers and 8 float registers that could +// be arguments. We also have a stack region from the previous +// stack frame that may hold some stack arguments. +// We need to write the integer registers to a memory region, write +// the float registers to a memory region (making sure we don't step +// on NAT while touching the registers). We also mark the memory +// address of the stack arguments. +// We then call PrepareAndDispatch() specifying the three memory +// region pointers. + + + .body + add out0 = 0, in0 // A move self ptr +// 144 bytes = 16 byte stack header + 64 byte int space + 64 byte float space +// methodIndex is at 144 + 16 bytes away from current sp +// (current frame + previous frame header) + ld8 out4 = [out4] // M restarg address + add r11 = 160, sp ;; // A address of methodIndex + + ld8 out1 = [r11] // M load methodIndex +// sp + 16 is the start of intargs + add out2 = 16, sp // A address of intargs +// the intargs take up 64 bytes, so sp + 16 + 64 is the start of floatargs + add out3 = 80, sp ;; // A address of floatargs + + add r11 = 0, out2 ;; // A + st8.spill [r11] = in1, 8 // M + add r10 = 0, out3 ;; // A + + st8.spill [r11] = in2, 8 ;; // M + st8.spill [r11] = in3, 8 // M + nop.i 0 ;; // I + + st8.spill [r11] = in4, 8 ;; // M + st8.spill [r11] = in5, 8 // M + nop.i 0 ;; // I + + st8.spill [r11] = in6, 8 ;; // M + st8.spill [r11] = in7 // M + fclass.nm p14,p15 = f8,@nat ;; // F + +(p14) stfd [r10] = f8, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 = f9,@nat ;; // F + +(p12) stfd [r10] = f9, 8 // M +(p13) add r10 = 8, r10 // A + fclass.nm p14,p15 =f10,@nat ;; // F + +(p14) stfd [r10] = f10, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 =f11,@nat ;; // F + +(p12) stfd [r10] = f11, 8 // M +(p13) add r10 = 8, r10 // A + fclass.nm p14,p15 =f12,@nat ;; // F + +(p14) stfd [r10] = f12, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 =f13,@nat ;; // F + +(p12) stfd [r10] = f13, 8 // M +(p13) add r10 = 8, r10 // A + fclass.nm p14,p15 =f14,@nat ;; // F + +(p14) stfd [r10] = f14, 8 // M +(p15) add r10 = 8, r10 // A + fclass.nm p12,p13 =f15,@nat ;; // F + +(p12) stfd [r10] = f15, 8 // M +(p13) add r10 = 8, r10 // A + +// branch to PrepareAndDispatch + br.call.dptk.few rp = PrepareAndDispatch ;; // B + +// epilog + mov ar.unat = r42 // M + mov ar.pfs = r41 // I + mov rp = r40 ;; // I + + add gp = 0, r43 // A + add sp = 144, sp // A + br.ret.dptk.few rp ;; // B + + .endp + +/* Magic indicating no need for an executable stack */ +.section .note.GNU-stack, "", @progbits diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_loongarch64.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_loongarch64.S new file mode 100644 index 0000000000..ae4e0cf73f --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_loongarch64.S @@ -0,0 +1,52 @@ +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + .set NGPRGES, 8 + .set NFPREGS, 8 + + .text + .globl SharedStub + .hidden SharedStub + .type SharedStub,@function + +SharedStub: + .cfi_startproc + move $t0, $sp + addi.d $sp, $sp, -8*(NGPRGES+NFPREGS)-16 + .cfi_def_cfa_offset 8*(NGPRGES+NFPREGS)+16 + st.d $a0, $sp, 0 + st.d $a1, $sp, 8 + st.d $a2, $sp, 16 + st.d $a3, $sp, 24 + st.d $a4, $sp, 32 + st.d $a5, $sp, 40 + st.d $a6, $sp, 48 + st.d $a7, $sp, 56 + fst.d $fa0, $sp, 64 + fst.d $fa1, $sp, 72 + fst.d $fa2, $sp, 80 + fst.d $fa3, $sp, 88 + fst.d $fa4, $sp, 96 + fst.d $fa5, $sp, 104 + fst.d $fa6, $sp, 112 + fst.d $fa7, $sp, 120 + st.d $ra, $sp, 136 + .cfi_offset 1, 136 + + /* methodIndex is passed from stub */ + move $a1, $t6 + move $a2, $t0 + move $a3, $sp + addi.d $a4, $sp, 8*NGPRGES + + bl PrepareAndDispatch + + ld.d $ra, $sp, 136 + .cfi_restore 1 + addi.d $sp, $sp, 8*(NGPRGES+NFPREGS)+16 + .cfi_def_cfa_offset -8*(NGPRGES+NFPREGS)-16 + jirl $zero, $ra, 0 + .cfi_endproc + + .size SharedStub, .-SharedStub + .section .note.GNU-stack, "", @progbits diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S new file mode 100644 index 0000000000..d17301634e --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S @@ -0,0 +1,116 @@ +/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* This code is for MIPS using the O32 ABI. */ + +#ifdef ANDROID +#include <asm/regdef.h> +#include <asm/asm.h> +#include <machine/asm.h> +#else +#include <sys/regdef.h> +#include <sys/asm.h> +#endif + +# NARGSAVE is the argument space in the callers frame, including extra +# 'shadowed' space for the argument registers. The minimum of 4 +# argument slots is sometimes predefined in the header files. +#ifndef NARGSAVE +#define NARGSAVE 4 +#endif + +#define LOCALSZ 2 /* gp, ra */ +#define FRAMESZ ((((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK) + +#define RAOFF (FRAMESZ - (1*SZREG)) +#define GPOFF (FRAMESZ - (2*SZREG)) + +#define A0OFF (FRAMESZ + (0*SZREG)) +#define A1OFF (FRAMESZ + (1*SZREG)) +#define A2OFF (FRAMESZ + (2*SZREG)) +#define A3OFF (FRAMESZ + (3*SZREG)) + + .text + +#define STUB_ENTRY(x) \ + .if x < 10; \ + .globl _ZN14nsXPTCStubBase5Stub ##x ##Ev; \ + .type _ZN14nsXPTCStubBase5Stub ##x ##Ev,@function; \ + .aent _ZN14nsXPTCStubBase5Stub ##x ##Ev,0; \ +_ZN14nsXPTCStubBase5Stub ##x ##Ev:; \ + SETUP_GP; \ + li t0,x; \ + b sharedstub; \ + .elseif x < 100; \ + .globl _ZN14nsXPTCStubBase6Stub ##x ##Ev; \ + .type _ZN14nsXPTCStubBase6Stub ##x ##Ev,@function; \ + .aent _ZN14nsXPTCStubBase6Stub ##x ##Ev,0; \ +_ZN14nsXPTCStubBase6Stub ##x ##Ev:; \ + SETUP_GP; \ + li t0,x; \ + b sharedstub; \ + .elseif x < 1000; \ + .globl _ZN14nsXPTCStubBase7Stub ##x ##Ev; \ + .type _ZN14nsXPTCStubBase7Stub ##x ##Ev,@function; \ + .aent _ZN14nsXPTCStubBase7Stub ##x ##Ev,0; \ +_ZN14nsXPTCStubBase7Stub ##x ##Ev:; \ + SETUP_GP; \ + li t0,x; \ + b sharedstub; \ + .else; \ + .err; \ + .endif + +# SENTINEL_ENTRY is handled in the cpp file. +#define SENTINEL_ENTRY(x) + +# +# open a dummy frame for the function entries +# + .align 2 + .type dummy,@function + .ent dummy, 0 + .frame sp, FRAMESZ, ra +dummy: + SETUP_GP + +#include "xptcstubsdef.inc" + +sharedstub: + subu sp, FRAMESZ + + # specify the save register mask for gp, ra, a0-a3 + .mask 0x900000F0, RAOFF-FRAMESZ + + sw ra, RAOFF(sp) + SAVE_GP(GPOFF) + + # Micro-optimization: a0 is already loaded, and its slot gets + # ignored by PrepareAndDispatch, so no need to save it here. + # sw a0, A0OFF(sp) + sw a1, A1OFF(sp) + sw a2, A2OFF(sp) + sw a3, A3OFF(sp) + + la t9, PrepareAndDispatch + + # t0 is methodIndex + move a1, t0 + # have a2 point to the begin of the argument space on stack + addiu a2, sp, FRAMESZ + + # PrepareAndDispatch(that, methodIndex, args) + jalr t9 + + # Micro-optimization: Using jalr explicitly has the side-effect + # of not triggering .cprestore. This is ok because we have no + # gp reference below this point. It also allows better + # instruction sscheduling. + # lw gp, GPOFF(fp) + + lw ra, RAOFF(sp) + addiu sp, FRAMESZ + j ra + END(dummy) diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4 new file mode 100644 index 0000000000..33c7b1492c --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4 @@ -0,0 +1,75 @@ +/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * Version: MPL 1.1 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* This code is for MIPS using the O32 ABI. */ + +#include <sys/regdef.h> +#include <sys/asm.h> + + .text + .globl PrepareAndDispatch + +NARGSAVE=4 # extra space for the callee to use. gccism + # we can put our a0-a3 in our callers space. +LOCALSZ=2 # gp, ra +FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK + +define(STUB_NAME, `Stub'$1`__14nsXPTCStubBase') + +define(STUB_ENTRY, +` .globl 'STUB_NAME($1)` + .align 2 + .type 'STUB_NAME($1)`,@function + .ent 'STUB_NAME($1)`, 0 +'STUB_NAME($1)`: + .frame sp, FRAMESZ, ra + .set noreorder + .cpload t9 + .set reorder + subu sp, FRAMESZ + .cprestore 16 + li t0, '$1` + b sharedstub +.end 'STUB_NAME($1)` + +') + +define(SENTINEL_ENTRY, `') + +include(xptcstubsdef.inc) + + .globl sharedstub + .ent sharedstub +sharedstub: + + REG_S ra, 20(sp) + + REG_S a0, 24(sp) + REG_S a1, 28(sp) + REG_S a2, 32(sp) + REG_S a3, 36(sp) + + # t0 is methodIndex + move a1, t0 + + # put the start of a1, a2, a3, and stack + move a2, sp + addi a2, 24 # have a2 point to sp + 24 (where a0 is) + + # PrepareAndDispatch(that, methodIndex, args) + # a0 a1 a2 + # + jal PrepareAndDispatch + + REG_L ra, 20(sp) + REG_L a1, 28(sp) + REG_L a2, 32(sp) + + addu sp, FRAMESZ + j ra + +.end sharedstub diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S new file mode 100644 index 0000000000..11d851536e --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S @@ -0,0 +1,111 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <sys/regdef.h> +#include <sys/asm.h> + +LOCALSZ=16 +FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK + +A1OFF=FRAMESZ-(9*SZREG) +A2OFF=FRAMESZ-(8*SZREG) +A3OFF=FRAMESZ-(7*SZREG) +A4OFF=FRAMESZ-(6*SZREG) +A5OFF=FRAMESZ-(5*SZREG) +A6OFF=FRAMESZ-(4*SZREG) +A7OFF=FRAMESZ-(3*SZREG) +GPOFF=FRAMESZ-(2*SZREG) +RAOFF=FRAMESZ-(1*SZREG) + +F13OFF=FRAMESZ-(16*SZREG) +F14OFF=FRAMESZ-(15*SZREG) +F15OFF=FRAMESZ-(14*SZREG) +F16OFF=FRAMESZ-(13*SZREG) +F17OFF=FRAMESZ-(12*SZREG) +F18OFF=FRAMESZ-(11*SZREG) +F19OFF=FRAMESZ-(10*SZREG) + +#define SENTINEL_ENTRY(n) /* defined in cpp file, not here */ + +#define STUB_ENTRY(x) \ + .if x < 10; \ + MAKE_STUB(x, _ZN14nsXPTCStubBase5Stub ##x ##Ev); \ + .elseif x < 100; \ + MAKE_STUB(x, _ZN14nsXPTCStubBase6Stub ##x ##Ev); \ + .elseif x < 1000; \ + MAKE_STUB(x, _ZN14nsXPTCStubBase7Stub ##x ##Ev); \ + .else; \ + .err; \ + .endif + +#define MAKE_STUB(x, name) \ + .globl name; \ + .type name,@function; \ + .aent name,0; \ +name:; \ + PTR_SUBU sp,FRAMESZ; \ + SETUP_GP64(GPOFF, name); \ + li t0,x; \ + b sharedstub; \ + +# +# open a dummy frame for the function entries +# + .text + .align 2 + .type dummy,@function + .ent dummy, 0 +dummy: + .frame sp, FRAMESZ, ra + .mask 0x90000FF0, RAOFF-FRAMESZ + .fmask 0x000FF000, F19OFF-FRAMESZ + +#include "xptcstubsdef.inc" + +sharedstub: + + REG_S a1, A1OFF(sp) + REG_S a2, A2OFF(sp) + REG_S a3, A3OFF(sp) + REG_S a4, A4OFF(sp) + REG_S a5, A5OFF(sp) + REG_S a6, A6OFF(sp) + REG_S a7, A7OFF(sp) + REG_S ra, RAOFF(sp) + + s.d $f13, F13OFF(sp) + s.d $f14, F14OFF(sp) + s.d $f15, F15OFF(sp) + s.d $f16, F16OFF(sp) + s.d $f17, F17OFF(sp) + s.d $f18, F18OFF(sp) + s.d $f19, F19OFF(sp) + + # t0 is methodIndex + move a1, t0 + + # a2 is stack address where extra function params + # are stored that do not fit in registers + move a2, sp + PTR_ADDI a2, FRAMESZ + + # a3 is stack address of a1..a7 + move a3, sp + PTR_ADDI a3, A1OFF + + # a4 is stack address of f13..f19 + move a4, sp + PTR_ADDI a4, F13OFF + + # PrepareAndDispatch(that, methodIndex, args, gprArgs, fpArgs) + # a0 a1 a2 a3 a4 + # + jal PrepareAndDispatch + + REG_L ra, RAOFF(sp) + RESTORE_GP64 + + PTR_ADDU sp, FRAMESZ + j ra + END(dummy) diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s new file mode 100644 index 0000000000..9e86848fcf --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s @@ -0,0 +1,68 @@ + .LEVEL 1.1 + +curframesz .EQU 128 +; SharedStub has stack size of 128 bytes + +lastframesz .EQU 64 +; the StubN C++ function has a small stack size of 64 bytes + + .SPACE $TEXT$,SORT=8 + .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24 +SharedStub + .PROC + .CALLINFO CALLER,FRAME=80,SAVE_RP,ARGS_SAVED + + .ENTRY + STW %rp,-20(%sp) + LDO 128(%sp),%sp + + STW %r19,-32(%r30) + STW %r26,-36-curframesz(%r30) ; save arg0 in previous frame + + LDO -80(%r30),%r28 + FSTD,MA %fr5,8(%r28) ; save darg0 + FSTD,MA %fr7,8(%r28) ; save darg1 + FSTW,MA %fr4L,4(%r28) ; save farg0 + FSTW,MA %fr5L,4(%r28) ; save farg1 + FSTW,MA %fr6L,4(%r28) ; save farg2 + FSTW,MA %fr7L,4(%r28) ; save farg3 + + ; Former value of register 26 is already properly saved by StubN, + ; but register 25-23 are not because of the arguments mismatch + STW %r25,-40-curframesz-lastframesz(%r30) ; save r25 + STW %r24,-44-curframesz-lastframesz(%r30) ; save r24 + STW %r23,-48-curframesz-lastframesz(%r30) ; save r23 + COPY %r26,%r25 ; method index is arg1 + LDW -36-curframesz-lastframesz(%r30),%r26 ; self is arg0 + LDO -40-curframesz-lastframesz(%r30),%r24 ; normal args is arg2 + LDO -80(%r30),%r23 ; floating args is arg3 + + BL .+8,%r2 + ADDIL L'PrepareAndDispatch-$PIC_pcrel$0+4,%r2 + LDO R'PrepareAndDispatch-$PIC_pcrel$1+8(%r1),%r1 +$PIC_pcrel$0 + LDSID (%r1),%r31 +$PIC_pcrel$1 + MTSP %r31,%sr0 + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR +;in=23-26;out=28; + BLE 0(%sr0,%r1) + COPY %r31,%r2 + + LDW -32(%r30),%r19 + + LDW -148(%sp),%rp + BVE (%rp) + .EXIT + LDO -128(%sp),%sp + + + .PROCEND ;in=26;out=28; + + .ALIGN 8 + .SPACE $TEXT$ + .SUBSPA $CODE$ + .IMPORT PrepareAndDispatch,CODE + .EXPORT SharedStub,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR,LONG_RETURN + .END + diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s new file mode 100644 index 0000000000..b45d7763be --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s @@ -0,0 +1,73 @@ +/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * Version: MPL 1.1 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .LEVEL 1.1 + .TEXT + .ALIGN 4 + +curframesz: + .EQU 128 + + +; SharedStub has stack size of 128 bytes + +lastframesz: + .EQU 64 + +; the StubN C++ function has a small stack size of 64 bytes + + +.globl SharedStub + .type SharedStub, @function + +SharedStub: + .PROC + .CALLINFO CALLER,FRAME=80,SAVE_RP + + .ENTRY + STW %rp,-20(%sp) + LDO 128(%sp),%sp + + STW %r19,-32(%r30) + STW %r26,-36-curframesz(%r30) ; save arg0 in previous frame + + LDO -80(%r30),%r28 + FSTD,MA %fr5,8(%r28) ; save darg0 + FSTD,MA %fr7,8(%r28) ; save darg1 + FSTW,MA %fr4L,4(%r28) ; save farg0 + FSTW,MA %fr5L,4(%r28) ; save farg1 + FSTW,MA %fr6L,4(%r28) ; save farg2 + FSTW,MA %fr7L,4(%r28) ; save farg3 + + ; Former value of register 26 is already properly saved by StubN, + ; but register 25-23 are not because of the argument mismatch + STW %r25,-40-curframesz-lastframesz(%r30) ; save r25 + STW %r24,-44-curframesz-lastframesz(%r30) ; save r24 + STW %r23,-48-curframesz-lastframesz(%r30) ; save r23 + COPY %r26,%r25 ; method index is arg1 + LDW -36-curframesz-lastframesz(%r30),%r26 ; self is arg0 + LDO -40-curframesz-lastframesz(%r30),%r24 ; normal args is arg2 + LDO -80(%r30),%r23 ; floating args is arg3 + + .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR ;in=23-26;out=28; + BL PrepareAndDispatch, %r31 + COPY %r31,%r2 + + LDW -32(%r30),%r19 + + LDW -148(%sp),%rp + LDO -128(%sp),%sp + + + BV,N (%rp) + NOP + NOP + + .EXIT + .PROCEND ;in=26;out=28; + + .SIZE SharedStub, .-SharedStub diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S new file mode 100644 index 0000000000..0b884e1fdb --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S @@ -0,0 +1,112 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set r1,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + +#if _CALL_ELF == 2 +#define STACK_PARAMS 96 +#else +#define STACK_PARAMS 112 +#endif + +#if _CALL_ELF == 2 + .section ".text" + .type SharedStub,@function + .globl SharedStub + # Make the symbol hidden so that the branch from the stub does + # not go via a PLT. This is not only better for performance, + # but may be necessary to avoid linker errors since there is + # no place to restore the TOC register in a sibling call. + .hidden SharedStub + .align 2 +SharedStub: +0: addis 2,12,(.TOC.-0b)@ha + addi 2,2,(.TOC.-0b)@l + .localentry SharedStub,.-SharedStub +#else + .section ".text" + .align 2 + .globl SharedStub + # Make the symbol hidden so that the branch from the stub does + # not go via a PLT. This is not only better for performance, + # but may be necessary to avoid linker errors since there is + # no place to restore the TOC register in a sibling call. + .hidden SharedStub + .section ".opd","aw" + .align 3 + +SharedStub: + .quad .SharedStub,.TOC.@tocbase + .previous + .type SharedStub,@function + +.SharedStub: +#endif + mflr r0 + + std r4, -56(r1) # Save all GPRS + std r5, -48(r1) + std r6, -40(r1) + std r7, -32(r1) + std r8, -24(r1) + std r9, -16(r1) + std r10, -8(r1) + + stfd f13, -64(r1) # ... and FPRS + stfd f12, -72(r1) + stfd f11, -80(r1) + stfd f10, -88(r1) + stfd f9, -96(r1) + stfd f8, -104(r1) + stfd f7, -112(r1) + stfd f6, -120(r1) + stfd f5, -128(r1) + stfd f4, -136(r1) + stfd f3, -144(r1) + stfd f2, -152(r1) + stfd f1, -160(r1) + + subi r6,r1,56 # r6 --> gprData + subi r7,r1,160 # r7 --> fprData + addi r5,r1,STACK_PARAMS # r5 --> extra stack args + + std r0, 16(r1) + + stdu r1,-288(r1) + # r3 has the 'self' pointer + # already + + mr r4,r11 # r4 is methodIndex selector, + # passed via r11 in the + # nsNSStubBase::StubXX() call + + bl PrepareAndDispatch + nop + + ld 1,0(r1) # restore stack + ld r0,16(r1) # restore LR + mtlr r0 + blr + +#if _CALL_ELF == 2 + .size SharedStub,.-SharedStub +#else + .size SharedStub,.-.SharedStub +#endif + + # Magic indicating no need for an executable stack + .section .note.GNU-stack, "", @progbits diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4 new file mode 100644 index 0000000000..6dabf334da --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4 @@ -0,0 +1,119 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + +# Define the correct name of the stub function based on the object model + +define(STUB_NAME, + ifelse(AIX_OBJMODEL, ibm, + `Stub'$1`__EI14nsXPTCStubBaseFv', + `Stub'$1`__14nsXPTCStubBaseFv')) + +define(STUB_ENTRY, ` + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.'STUB_NAME($1)`{TC},"'STUB_NAME($1)`" + .csect H.10.NO_SYMBOL{PR} + .globl .'STUB_NAME($1)` + .globl 'STUB_NAME($1)`{DS} + +.'STUB_NAME($1)`: + li r12, '$1` + b .SharedStub + nop + + + .toc +T.18.'STUB_NAME($1)`: + .tc H.18.'STUB_NAME($1)`{TC},'STUB_NAME($1)`{DS} + .csect 'STUB_NAME($1)`{DS} + .long .'STUB_NAME($1)` + .long TOC{TC0} + .long 0x00000000 +') + +define(SENTINEL_ENTRY, `') + +include(xptcstubsdef.inc) + + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.SharedStub{TC},"SharedStub" + +# .text section + .csect H.10.NO_SYMBOL{PR} + .globl .SharedStub + .globl SharedStub{DS} + .extern .PrepareAndDispatch + +.SharedStub: + mflr r0 + stw r0,8(sp) + + stwu sp,-176(sp) # room for linkage (24), fprData (104), gprData(28) + # outgoing params to PrepareAndDispatch (20) + + stw r4,44(sp) # link area (24) + PrepareAndDispatch params (20) + stw r5,48(sp) + stw r6,52(sp) + stw r7,56(sp) + stw r8,60(sp) + stw r9,64(sp) + stw r10,68(sp) + stfd f1,72(sp) + stfd f2,80(sp) + stfd f3,88(sp) + stfd f4,96(sp) + stfd f5,104(sp) + stfd f6,112(sp) + stfd f7,120(sp) + stfd f8,128(sp) + stfd f9,136(sp) + stfd f10,144(sp) + stfd f11,152(sp) + stfd f12,156(sp) + stfd f13,164(sp) + + addi r6,sp,44 # gprData + + addi r7,sp,72 # fprData + # r3 has the 'self' pointer already + mr r4,r12 # methodIndex selector (it is now LATER) + addi r5,sp,232 # pointer to callers args area, beyond r3-r10 + # mapped range + + bl .PrepareAndDispatch + nop + + + lwz r0,184(sp) + addi sp,sp,176 + mtlr r0 + blr + +# .data section + + .toc # 0x00000038 +T.18.SharedStub: + .tc H.18.SharedStub{TC},SharedStub{DS} + + .csect SharedStub{DS} + .long .SharedStub # "\0\0\0\0" + .long TOC{TC0} # "\0\0\0008" + .long 0x00000000 # "\0\0\0\0" +# End csect SharedStub{DS} + +# .bss section diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4 new file mode 100644 index 0000000000..24d713cc9b --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4 @@ -0,0 +1,97 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 +# Define the correct name of the stub function based on the object model +define(STUB_NAME, + ifelse(AIX_OBJMODEL, ibm, + `Stub'$1`__EI14nsXPTCStubBaseFv', + `Stub'$1`__14nsXPTCStubBaseFv')) +define(STUB_ENTRY, ` + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.'STUB_NAME($1)`{TC},"'STUB_NAME($1)`" + .csect H.10.NO_SYMBOL{PR} + .globl .'STUB_NAME($1)` + .globl 'STUB_NAME($1)`{DS} +.'STUB_NAME($1)`: + li r12, '$1` + b .SharedStub + nop + .toc +T.18.'STUB_NAME($1)`: + .tc H.18.'STUB_NAME($1)`{TC},'STUB_NAME($1)`{DS} + .csect 'STUB_NAME($1)`{DS} + .llong .'STUB_NAME($1)` + .llong TOC{TC0} + .llong 0x00000000 +') +define(SENTINEL_ENTRY, `') +include(xptcstubsdef.inc) + .rename H.10.NO_SYMBOL{PR},"" + .rename H.18.SharedStub{TC},"SharedStub" +# .text section + .csect H.10.NO_SYMBOL{PR} + .globl .SharedStub + .globl SharedStub{DS} + .extern .PrepareAndDispatch +.SharedStub: + mflr r0 + std r0,16(sp) + stdu sp,-248(sp) # room for linkage (24*2), fprData (104), gprData(28*2) + # outgoing params to PrepareAndDispatch (40) + std r4,88(sp) # link area (48) + PrepareAndDispatch params (20) + std r5,96(sp) + std r6,104(sp) + std r7,112(sp) + std r8,120(sp) + std r9,128(sp) + std r10,136(sp) + stfd f1,144(sp) + stfd f2,152(sp) + stfd f3,160(sp) + stfd f4,168(sp) + stfd f5,176(sp) + stfd f6,184(sp) + stfd f7,192(sp) + stfd f8,200(sp) + stfd f9,208(sp) + stfd f10,216(sp) + stfd f11,224(sp) + stfd f12,232(sp) + stfd f13,240(sp) + addi r6,sp,88 # gprData + addi r7,sp,144 # fprData + # r3 has the 'self' pointer already + mr r4,r12 # methodIndex selector (it is now LATER) + addi r5,sp,360 # pointer to callers args area, beyond r3-r10 + # mapped range + bl .PrepareAndDispatch + nop + ld r0,264(sp) + addi sp,sp,248 + mtlr r0 + blr +# .data section + .toc # 0x00000038 +T.18.SharedStub: + .tc H.18.SharedStub{TC},SharedStub{DS} + .csect SharedStub{DS} + .llong .SharedStub # "\0\0\0\0" + .llong TOC{TC0} # "\0\0\0008" + .llong 0x00000000 # "\0\0\0\0" +# End csect SharedStub{DS} +# .bss section diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4 new file mode 100644 index 0000000000..dda5378503 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4 @@ -0,0 +1,114 @@ +/* -*- Mode: asm -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .text + .globl _SharedStub +dnl +define(STUB_MANGLED_ENTRY, +` .globl '$2` + .align 2 +'$2`: + addi r12, 0,'$1` + b _SharedStub') +dnl +define(STUB_ENTRY, +` .if '$1` < 10 +STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase5Stub'$1`Ev') + .elseif '$1` < 100 +STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase6Stub'$1`Ev') + .elseif '$1` < 1000 +STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase7Stub'$1`Ev') + .else + .err "Stub'$1` >= 1000 not yet supported." + .endif +') +dnl +define(SENTINEL_ENTRY, `') +dnl +include(xptcstubsdef.inc) +dnl +// See also xptcstubs_ppc_rhapsody.cpp:PrepareAndDispatch. +_SharedStub: + // Prolog(ue) + mflr r0 // Save the link register in the caller's + stw r0, 8(r1) // stack frame + stwu r1,-176(r1) // Allocate stack space for our own frame and + // adjust stack pointer + + // Linkage area, 0(r1) to 24(r1) + // Original sp saved at 0(r1) + + // Parameter area, 20 bytes from 24(r1) to + // 44(r1) to accomodate 5 arguments passed + // to PrepareAndDispatch + + // Local variables, 132 bytes from 44(r1) + // to 176(r1), to accomodate 5 words and + // 13 doubles + + stw r4, 44(r1) // Save parameters passed in GPRs r4-r10; + stw r5, 48(r1) // a pointer to here will be passed to + stw r6, 52(r1) // PrepareAndDispatch for access to + stw r7, 56(r1) // arguments passed in registers. r3, + stw r8, 60(r1) // the self pointer, is used for the + stw r9, 64(r1) // call but isn't otherwise needed in + stw r10, 68(r1) // PrepareAndDispatch, so it is not saved. + + stfd f1, 72(r1) // Do the same for floating-point parameters + stfd f2, 80(r1) // passed in FPRs f1-f13 + stfd f3, 88(r1) + stfd f4, 96(r1) + stfd f5, 104(r1) + stfd f6, 112(r1) + stfd f7, 120(r1) + stfd f8, 128(r1) + stfd f9, 136(r1) + stfd f10, 144(r1) + stfd f11, 152(r1) + stfd f12, 160(r1) + stfd f13, 168(r1) + + // Set up parameters for call to + // PrepareAndDispatch. argument= + // 0, pointer to self, already in r3 + mr r4,r12 // 1, stub number + addi r5, r1, 204 // 2, pointer to the parameter area in our + // caller's stack, for access to + // parameters beyond those passed in + // registers. Skip past the first parameter + // (corresponding to r3) for the same reason + // as above. 176 (size of our frame) + 24 + // (size of caller's linkage) + 4 (skipped + // parameter) + addi r6, r1, 44 // 3, pointer to saved GPRs + addi r7, r1, 72 // 4, pointer to saved FPRs + + bl L_PrepareAndDispatch$stub + // Do it + nop // Leave room for linker magic + + // Epilog(ue) + lwz r0, 184(r1) // Retrieve old link register value + addi r1, r1, 176 // Restore stack pointer + mtlr r0 // Restore link register + blr // Return + +.picsymbol_stub +L_PrepareAndDispatch$stub: // Standard PIC symbol stub + .indirect_symbol _PrepareAndDispatch + mflr r0 + bcl 20,31,L1$pb +L1$pb: + mflr r11 + addis r11,r11,ha16(L1$lz-L1$pb) + mtlr r0 + lwz r12,lo16(L1$lz-L1$pb)(r11) + mtctr r12 + addi r11,r11,lo16(L1$lz-L1$pb) + bctr +.lazy_symbol_pointer +L1$lz: + .indirect_symbol _PrepareAndDispatch + .long dyld_stub_binding_helper diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S new file mode 100644 index 0000000000..e383468865 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S @@ -0,0 +1,77 @@ +// -*- Mode: Asm -*- +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + + .section ".text" + .align 2 + .globl SharedStub + .type SharedStub,@function + +SharedStub: + stwu sp,-112(sp) // room for + // linkage (8), + // gprData (32), + // fprData (64), + // stack alignment(8) + mflr r0 + stw r0,116(sp) // save LR backchain + + stw r4,12(sp) // save GP registers + stw r5,16(sp) // (n.b. that we don't save r3 + stw r6,20(sp) // because PrepareAndDispatch() is savvy) + stw r7,24(sp) + stw r8,28(sp) + stw r9,32(sp) + stw r10,36(sp) +#ifndef __NO_FPRS__ + stfd f1,40(sp) // save FP registers + stfd f2,48(sp) + stfd f3,56(sp) + stfd f4,64(sp) + stfd f5,72(sp) + stfd f6,80(sp) + stfd f7,88(sp) + stfd f8,96(sp) +#endif + + // r3 has the 'self' pointer already + + mr r4,r11 // r4 <= methodIndex selector, passed + // via r11 in the nsXPTCStubBase::StubXX() call + + addi r5,sp,120 // r5 <= pointer to callers args area, + // beyond r3-r10/f1-f8 mapped range + + addi r6,sp,8 // r6 <= gprData +#ifndef __NO_FPRS__ + addi r7,sp,40 // r7 <= fprData +#else + li r7, 0 // r7 should be unused +#endif + + bl PrepareAndDispatch@local // Go! + + lwz r0,116(sp) // restore LR + mtlr r0 + la sp,112(sp) // clean up the stack + blr + + /* Magic indicating no need for an executable stack */ + .section .note.GNU-stack, "", @progbits diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S new file mode 100644 index 0000000000..968ad428f8 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S @@ -0,0 +1,72 @@ +// -*- Mode: Asm -*- +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31 +.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4 +.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9 +.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14 +.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19 +.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24 +.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29 +.set f30,30; .set f31,31 + + .section ".text" + .align 2 + .globl SharedStub + .type SharedStub,@function + +SharedStub: + stwu sp,-112(sp) // room for + // linkage (8), + // gprData (32), + // fprData (64), + // stack alignment(8) + mflr r0 + stw r0,116(sp) // save LR backchain + + stw r4,12(sp) // save GP registers + stw r5,16(sp) // (n.b. that we don't save r3 + stw r6,20(sp) // because PrepareAndDispatch() is savvy) + stw r7,24(sp) + stw r8,28(sp) + stw r9,32(sp) + stw r10,36(sp) + + stfd f1,40(sp) // save FP registers + stfd f2,48(sp) + stfd f3,56(sp) + stfd f4,64(sp) + stfd f5,72(sp) + stfd f6,80(sp) + stfd f7,88(sp) + stfd f8,96(sp) + + // r3 has the 'self' pointer already + + mr r4,r11 // r4 <= methodIndex selector, passed + // via r11 in the nsXPTCStubBase::StubXX() call + + addi r5,sp,120 // r5 <= pointer to callers args area, + // beyond r3-r10/f1-f8 mapped range + + addi r6,sp,8 // r6 <= gprData + addi r7,sp,40 // r7 <= fprData + + bl PrepareAndDispatch@local // Go! + + lwz r0,116(sp) // restore LR + mtlr r0 + la sp,112(sp) // clean up the stack + blr + + // Magic indicating no need for an executable stack + .section .note.GNU-stack, "", @progbits diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_riscv64.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_riscv64.S new file mode 100644 index 0000000000..02bb812d59 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_riscv64.S @@ -0,0 +1,53 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + .set NGPREGS, 8 + .set NFPREGS, 8 + + .text + .globl SharedStub + .hidden SharedStub + .type SharedStub,@function + +SharedStub: + .cfi_startproc + mv t1, sp + addi sp, sp, -8*(NGPREGS+NFPREGS)-16 + .cfi_adjust_cfa_offset 8*(NGPREGS+NFPREGS)+16 + sd a0, 0(sp) + sd a1, 8(sp) + sd a2, 16(sp) + sd a3, 24(sp) + sd a4, 32(sp) + sd a5, 40(sp) + sd a6, 48(sp) + sd a7, 56(sp) + fsd fa0, 64(sp) + fsd fa1, 72(sp) + fsd fa2, 80(sp) + fsd fa3, 88(sp) + fsd fa4, 96(sp) + fsd fa5, 104(sp) + fsd fa6, 112(sp) + fsd fa7, 120(sp) + sd ra, 136(sp) + .cfi_rel_offset ra, 136 + + /* methodIndex is passed from stub */ + mv a1, t0 + mv a2, t1 + mv a3, sp + addi a4, sp, 8*NGPREGS + + call PrepareAndDispatch + + ld ra, 136(sp) + .cfi_restore ra + addi sp, sp, 8*(NGPREGS+NFPREGS)+16 + .cfi_adjust_cfa_offset -8*(NGPREGS+NFPREGS)-16 + ret + .cfi_endproc + + .size SharedStub, . - SharedStub + .section .note.GNU-stack, "", @progbits diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s new file mode 100644 index 0000000000..ab97a890c3 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s @@ -0,0 +1,50 @@ +/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .global SharedStub + +/* + in the frame for the function that called SharedStub are the + rest of the parameters we need + +*/ + +SharedStub: +! we don't create a new frame yet, but work within the frame of the calling +! function to give ourselves the other parameters we want + + mov %o0, %o1 ! shuffle the index up to 2nd place + mov %i0, %o0 ! the original 'this' + add %fp, 0x7ff + 136, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this') + +! save off the original incoming parameters that arrived in +! registers, the ABI guarantees the space for us to do this + stx %i1, [%fp + 0x7ff + 136] + stx %i2, [%fp + 0x7ff + 144] + stx %i3, [%fp + 0x7ff + 152] + stx %i4, [%fp + 0x7ff + 160] + stx %i5, [%fp + 0x7ff + 168] +! now we can build our own stack frame + save %sp,-(128 + 64),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 64 +! our function now appears to have been called +! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args) +! so we can just copy these through + + mov %i0, %o0 + mov %i1, %o1 + mov %i2, %o2 + call PrepareAndDispatch + nop + mov %o0,%i0 ! propagate return value + b .LL1 + nop +.LL1: + ret + restore + + .size SharedStub, .-SharedStub + .type SharedStub, #function diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s new file mode 100644 index 0000000000..9b448d7c7d --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .global SharedStub + +/* + in the frame for the function that called SharedStub are the + rest of the parameters we need + +*/ + +SharedStub: +! we don't create a new frame yet, but work within the frame of the calling +! function to give ourselves the other parameters we want + + mov %o0, %o1 ! shuffle the index up to 2nd place + mov %i0, %o0 ! the original 'this' + add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this') +! save off the original incoming parameters that arrived in +! registers, the ABI guarantees the space for us to do this + st %i1, [%fp + 72] + st %i2, [%fp + 76] + st %i3, [%fp + 80] + st %i4, [%fp + 84] + st %i5, [%fp + 88] +! now we can build our own stack frame + save %sp,-(64 + 32),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 32 +! our function now appears to have been called +! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args) +! so we can just copy these through + + mov %i0, %o0 + mov %i1, %o1 + mov %i2, %o2 + call PrepareAndDispatch + nop + mov %o0,%i0 ! propagate return value + b .LL1 + nop +.LL1: + ret + restore + + .size SharedStub, .-SharedStub + .type SharedStub, #function diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s new file mode 100644 index 0000000000..871556d4c6 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .global SharedStub + +/* + in the frame for the function that called SharedStub are the + rest of the parameters we need + +*/ + +SharedStub: +! we don't create a new frame yet, but work within the frame of the calling +! function to give ourselves the other parameters we want + + mov %o0, %o1 ! shuffle the index up to 2nd place + mov %i0, %o0 ! the original 'this' + add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this') +! save off the original incoming parameters that arrived in +! registers, the ABI guarantees the space for us to do this + st %i1, [%fp + 72] + st %i2, [%fp + 76] + st %i3, [%fp + 80] + st %i4, [%fp + 84] + st %i5, [%fp + 88] +! now we can build our own stack frame + save %sp,-(64 + 32),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 32 +! our function now appears to have been called +! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args) +! so we can just copy these through + + mov %i0, %o0 + mov %i1, %o1 + mov %i2, %o2 + call PrepareAndDispatch + nop + mov %o0,%i0 ! propagate return value + b .LL1 + nop +.LL1: + ret + restore + + .size SharedStub, .-SharedStub + .type SharedStub, #function diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s new file mode 100644 index 0000000000..9b448d7c7d --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + .global SharedStub + +/* + in the frame for the function that called SharedStub are the + rest of the parameters we need + +*/ + +SharedStub: +! we don't create a new frame yet, but work within the frame of the calling +! function to give ourselves the other parameters we want + + mov %o0, %o1 ! shuffle the index up to 2nd place + mov %i0, %o0 ! the original 'this' + add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this') +! save off the original incoming parameters that arrived in +! registers, the ABI guarantees the space for us to do this + st %i1, [%fp + 72] + st %i2, [%fp + 76] + st %i3, [%fp + 80] + st %i4, [%fp + 84] + st %i5, [%fp + 88] +! now we can build our own stack frame + save %sp,-(64 + 32),%sp ! room for the register window and + ! struct pointer, rounded up to 0 % 32 +! our function now appears to have been called +! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args) +! so we can just copy these through + + mov %i0, %o0 + mov %i1, %o1 + mov %i2, %o2 + call PrepareAndDispatch + nop + mov %o0,%i0 ! propagate return value + b .LL1 + nop +.LL1: + ret + restore + + .size SharedStub, .-SharedStub + .type SharedStub, #function diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp new file mode 100644 index 0000000000..3d1addedaf --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp @@ -0,0 +1,18 @@ +/* -*- Mode: C -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#if defined(__i386__) +#include "xptcstubs_gcc_x86_unix.cpp" +#elif defined(__x86_64__) +#include "xptcstubs_x86_64_darwin.cpp" +#elif defined(__ppc__) +#include "xptcstubs_ppc_rhapsody.cpp" +#elif defined(__arm__) +#include "xptcstubs_arm.cpp" +#elif defined(__aarch64__) +#include "xptcstubs_aarch64.cpp" +#else +#error unknown cpu architecture +#endif diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp new file mode 100644 index 0000000000..5f0c3ba04e --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp @@ -0,0 +1,132 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" +#include "xptc_gcc_x86_unix.h" + +extern "C" { +static nsresult ATTRIBUTE_USED +__attribute__ ((regparm (3))) +PrepareAndDispatch(uint32_t methodIndex, nsXPTCStubBase* self, uint32_t* args) +{ + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) + ap++; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + dp->val.p = (void*) *ap; + switch(type) + { + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break; + default : break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} +} // extern "C" + +#if !defined(XP_MACOSX) + +#define STUB_HEADER(a, b) ".hidden " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev\n\t" \ + ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev,@function\n" + +#define STUB_SIZE(a, b) ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev\n\t" + +#else + +#define STUB_HEADER(a, b) +#define STUB_SIZE(a, b) + +#endif + +// gcc3 mangling tends to insert the length of the method name +#define STUB_ENTRY(n) \ +asm(".text\n\t" \ + ".align 2\n\t" \ + ".if " #n " < 10\n\t" \ + ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \ + STUB_HEADER(5, n) \ + SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \ + ".elseif " #n " < 100\n\t" \ + ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \ + STUB_HEADER(6, n) \ + SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \ + ".elseif " #n " < 1000\n\t" \ + ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \ + STUB_HEADER(7, n) \ + SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \ + ".else\n\t" \ + ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \ + ".endif\n\t" \ + "movl $" #n ", %eax\n\t" \ + "jmp " SYMBOL_UNDERSCORE "SharedStub\n\t" \ + ".if " #n " < 10\n\t" \ + STUB_SIZE(5, n) \ + ".elseif " #n " < 100\n\t" \ + STUB_SIZE(6, n) \ + ".else\n\t" \ + STUB_SIZE(7, n) \ + ".endif"); + +// static nsresult SharedStub(uint32_t methodIndex) __attribute__((regparm(1))) +asm(".text\n\t" + ".align 2\n\t" +#if !defined(XP_MACOSX) + ".type " SYMBOL_UNDERSCORE "SharedStub,@function\n\t" +#endif + SYMBOL_UNDERSCORE "SharedStub:\n\t" + "leal 0x08(%esp), %ecx\n\t" + "movl 0x04(%esp), %edx\n\t" + "jmp " SYMBOL_UNDERSCORE "PrepareAndDispatch\n\t" +#if !defined(XP_MACOSX) + ".size " SYMBOL_UNDERSCORE "SharedStub,.-" SYMBOL_UNDERSCORE "SharedStub" +#endif +); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +void +xptc_dummy() +{ +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp new file mode 100644 index 0000000000..4bee192886 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp @@ -0,0 +1,139 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +#include "xptcprivate.h" + +#include <stddef.h> +#include <stdlib.h> + +// "This code is for IA64 only" + +/* Implement shared vtbl methods. */ + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, + uint64_t* intargs, uint64_t* floatargs, uint64_t* restargs) +{ + + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint64_t* iargs = intargs; + uint64_t* fargs = floatargs; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + for(i = 0; i < paramCount; ++i) + { + int isfloat = 0; + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + MOZ_CRASH("NYI: support implicit JSContext*, bug 1475699"); + + if(param.IsOut() || !type.IsArithmetic()) + { +#ifdef __LP64__ + /* 64 bit pointer mode */ + dp->val.p = (void*) *iargs; +#else + /* 32 bit pointer mode */ + uint32_t* adr = (uint32_t*) iargs; + dp->val.p = (void*) (*(adr+1)); +#endif + } + else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *(iargs); break; + case nsXPTType::T_I16 : dp->val.i16 = *(iargs); break; + case nsXPTType::T_I32 : dp->val.i32 = *(iargs); break; + case nsXPTType::T_I64 : dp->val.i64 = *(iargs); break; + case nsXPTType::T_U8 : dp->val.u8 = *(iargs); break; + case nsXPTType::T_U16 : dp->val.u16 = *(iargs); break; + case nsXPTType::T_U32 : dp->val.u32 = *(iargs); break; + case nsXPTType::T_U64 : dp->val.u64 = *(iargs); break; + case nsXPTType::T_FLOAT : + isfloat = 1; + if (i < 7) + dp->val.f = (float) *((double*) fargs); /* register */ + else + dp->val.u32 = *(fargs); /* memory */ + break; + case nsXPTType::T_DOUBLE : + isfloat = 1; + dp->val.u64 = *(fargs); + break; + case nsXPTType::T_BOOL : dp->val.b = *(iargs); break; + case nsXPTType::T_CHAR : dp->val.c = *(iargs); break; + case nsXPTType::T_WCHAR : dp->val.wc = *(iargs); break; + default: + NS_ERROR("bad type"); + break; + } + if (i < 7) + { + /* we are parsing register arguments */ + if (i == 6) + { + // run out of register arguments, move on to memory arguments + iargs = restargs; + fargs = restargs; + } + else + { + ++iargs; // advance one integer register slot + if (isfloat) ++fargs; // advance float register slot if isfloat + } + } + else + { + /* we are parsing memory arguments */ + ++iargs; + ++fargs; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t) methodIndex, info, + paramBuffer); + + return result; +} + +extern "C" nsresult SharedStub(uint64_t,uint64_t,uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t *); + +/* Variable a0-a7 were put there so we can have access to the 8 input + registers on Stubxyz entry */ + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n(uint64_t a1, \ +uint64_t a2,uint64_t a3,uint64_t a4,uint64_t a5,uint64_t a6,uint64_t a7, \ +uint64_t a8) \ +{ uint64_t a0 = (uint64_t) this; \ + return SharedStub(a0,a1,a2,a3,a4,a5,a6,a7,(uint64_t) n, &a8); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp new file mode 100644 index 0000000000..cc74e4db57 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp @@ -0,0 +1,142 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +#include "xptcprivate.h" + +#include <stddef.h> +#include <stdlib.h> +#include <stdint.h> + +// "This code is for IA64 only" + +/* Implement shared vtbl methods. */ + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, + uint64_t* intargs, uint64_t* floatargs, uint64_t* restargs) +{ + + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint64_t* iargs = intargs; + uint64_t* fargs = floatargs; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (! info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + for(i = 0; i < paramCount; ++i) + { + int isfloat = 0; + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + MOZ_CRASH("NYI: support implicit JSContext*, bug 1475699"); + + if(param.IsOut() || !type.IsArithmetic()) + { +#ifdef __LP64__ + /* 64 bit pointer mode */ + dp->val.p = (void*) *iargs; +#else + /* 32 bit pointer mode */ + uint32_t* adr = (uint32_t*) iargs; + dp->val.p = (void*) (*(adr+1)); +#endif + } + else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *(iargs); break; + case nsXPTType::T_I16 : dp->val.i16 = *(iargs); break; + case nsXPTType::T_I32 : dp->val.i32 = *(iargs); break; + case nsXPTType::T_I64 : dp->val.i64 = *(iargs); break; + case nsXPTType::T_U8 : dp->val.u8 = *(iargs); break; + case nsXPTType::T_U16 : dp->val.u16 = *(iargs); break; + case nsXPTType::T_U32 : dp->val.u32 = *(iargs); break; + case nsXPTType::T_U64 : dp->val.u64 = *(iargs); break; + case nsXPTType::T_FLOAT : + isfloat = 1; + if (i < 7) + dp->val.f = (float) *((double*) fargs); /* register */ + else + dp->val.u32 = *(fargs); /* memory */ + break; + case nsXPTType::T_DOUBLE : + isfloat = 1; + dp->val.u64 = *(fargs); + break; + case nsXPTType::T_BOOL : dp->val.b = *(iargs); break; + case nsXPTType::T_CHAR : dp->val.c = *(iargs); break; + case nsXPTType::T_WCHAR : dp->val.wc = *(iargs); break; + default: + NS_ERROR("bad type"); + break; + } + if (i < 7) + { + /* we are parsing register arguments */ + if (i == 6) + { + // run out of register arguments, move on to memory arguments + iargs = restargs; + fargs = restargs; + } + else + { + ++iargs; // advance one integer register slot + if (isfloat) ++fargs; // advance float register slot if isfloat + } + } + else + { + /* we are parsing memory arguments */ + ++iargs; + ++fargs; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t) methodIndex, info, + paramBuffer); + + return result; +} + +extern "C" nsresult SharedStub(uint64_t,uint64_t,uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t *); + +/* Variable a0-a7 were put there so we can have access to the 8 input + registers on Stubxyz entry */ + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n(uint64_t a1, \ +uint64_t a2,uint64_t a3,uint64_t a4,uint64_t a5,uint64_t a6,uint64_t a7, \ +uint64_t a8) \ +{ uint64_t a0 = (uint64_t) this; \ + return SharedStub(a0,a1,a2,a3,a4,a5,a6,a7,(uint64_t) n, &a8); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp new file mode 100644 index 0000000000..74ffa0c539 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp @@ -0,0 +1,179 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +/* Prototype specifies unmangled function name and disables unused warning */ +static nsresult +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args) +__asm__("PrepareAndDispatch") ATTRIBUTE_USED; + +static nsresult +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args) +{ + const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + // args[0] to args[NUM_ARG_REGS] hold floating point register values + uint64_t* ap = args + NUM_ARG_REGS; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) + ap++; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = (int8_t) *ap; break; + case nsXPTType::T_I16 : dp->val.i16 = (int16_t) *ap; break; + case nsXPTType::T_I32 : dp->val.i32 = (int32_t) *ap; break; + case nsXPTType::T_I64 : dp->val.i64 = (int64_t) *ap; break; + case nsXPTType::T_U8 : dp->val.u8 = (uint8_t) *ap; break; + case nsXPTType::T_U16 : dp->val.u16 = (uint16_t) *ap; break; + case nsXPTType::T_U32 : dp->val.u32 = (uint32_t) *ap; break; + case nsXPTType::T_U64 : dp->val.u64 = (uint64_t) *ap; break; + case nsXPTType::T_FLOAT : + if(i < NUM_ARG_REGS) + { + // floats passed via registers are stored as doubles + // in the first NUM_ARG_REGS entries in args + dp->val.u64 = (uint64_t) args[i]; + dp->val.f = (float) dp->val.d; // convert double to float + } + else + dp->val.u32 = (uint32_t) *ap; + break; + case nsXPTType::T_DOUBLE : + // doubles passed via registers are also stored + // in the first NUM_ARG_REGS entries in args + dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap; + break; + case nsXPTType::T_BOOL : dp->val.b = (bool) *ap; break; + case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break; + case nsXPTType::T_WCHAR : dp->val.wc = (char16_t) *ap; break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +/* + * SharedStub() + * Collects arguments and calls PrepareAndDispatch. The "methodIndex" is + * passed to this function via $1 to preserve the argument registers. + */ +__asm__( + "#### SharedStub ####\n" +".text\n\t" + ".align 5\n\t" + ".ent SharedStub\n" +"SharedStub:\n\t" + ".frame $30,96,$26,0\n\t" + ".mask 0x4000000,-96\n\t" + "ldgp $29,0($27)\n" +"$SharedStub..ng:\n\t" + "subq $30,96,$30\n\t" + "stq $26,0($30)\n\t" + ".prologue 1\n\t" + + /* + * Store arguments passed via registers to the stack. + * Floating point registers are stored as doubles and converted + * to floats in PrepareAndDispatch if necessary. + */ + "stt $f17,16($30)\n\t" /* floating point registers */ + "stt $f18,24($30)\n\t" + "stt $f19,32($30)\n\t" + "stt $f20,40($30)\n\t" + "stt $f21,48($30)\n\t" + "stq $17,56($30)\n\t" /* integer registers */ + "stq $18,64($30)\n\t" + "stq $19,72($30)\n\t" + "stq $20,80($30)\n\t" + "stq $21,88($30)\n\t" + + /* + * Call PrepareAndDispatch function. + */ + "bis $1,$1,$17\n\t" /* pass "methodIndex" */ + "addq $30,16,$18\n\t" /* pass "args" */ + "bsr $26,$PrepareAndDispatch..ng\n\t" + + "ldq $26,0($30)\n\t" + "addq $30,96,$30\n\t" + "ret $31,($26),1\n\t" + ".end SharedStub" + ); + +/* + * nsresult nsXPTCStubBase::Stub##n() + * Sets register $1 to "methodIndex" and jumps to SharedStub. + */ +#define STUB_MANGLED_ENTRY(n, symbol) \ + "#### Stub"#n" ####" "\n\t" \ + ".text" "\n\t" \ + ".align 5" "\n\t" \ + ".globl " symbol "\n\t" \ + ".ent " symbol "\n" \ +symbol ":" "\n\t" \ + ".frame $30,0,$26,0" "\n\t" \ + "ldgp $29,0($27)" "\n" \ +"$" symbol "..ng:" "\n\t" \ + ".prologue 1" "\n\t" \ + "lda $1,"#n "\n\t" \ + "br $31,$SharedStub..ng" "\n\t" \ + ".end " symbol + +#define STUB_ENTRY(n) \ +__asm__( \ + ".if "#n" < 10" "\n\t" \ + STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase5Stub"#n"Ev") "\n\t" \ + ".elseif "#n" < 100" "\n\t" \ + STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase6Stub"#n"Ev") "\n\t" \ + ".elseif "#n" < 1000" "\n\t" \ + STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase7Stub"#n"Ev") "\n\t" \ + ".else" "\n\t" \ + ".err \"Stub"#n" >= 1000 not yet supported.\"" "\n\t" \ + ".endif" \ + ); + + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp new file mode 100644 index 0000000000..15665de872 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp @@ -0,0 +1,178 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +static nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, + uint32_t* a_gpr, uint64_t *a_fpr, uint32_t *a_ov) +{ + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no info"); + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint32_t gpr = 1, fpr = 0; + + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (gpr < 5) + a_gpr++, gpr++; + else + a_ov++; + } + + if(param.IsOut() || !type.IsArithmetic()) + { + if (gpr < 5) + dp->val.p = (void*) *a_gpr++, gpr++; + else + dp->val.p = (void*) *a_ov++; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : + if (gpr < 5) + dp->val.i8 = *((int32_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i8 = *((int32_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_I16 : + if (gpr < 5) + dp->val.i16 = *((int32_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i16 = *((int32_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_I32 : + if (gpr < 5) + dp->val.i32 = *((int32_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i32 = *((int32_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_I64 : + if (gpr < 4) + dp->val.i64 = *((int64_t*) a_gpr), a_gpr+=2, gpr+=2; + else + dp->val.i64 = *((int64_t*) a_ov ), a_ov+=2, gpr=5; + break; + case nsXPTType::T_U8 : + if (gpr < 5) + dp->val.u8 = *((uint32_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u8 = *((uint32_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_U16 : + if (gpr < 5) + dp->val.u16 = *((uint32_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u16 = *((uint32_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_U32 : + if (gpr < 5) + dp->val.u32 = *((uint32_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u32 = *((uint32_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_U64 : + if (gpr < 4) + dp->val.u64 = *((uint64_t*)a_gpr), a_gpr+=2, gpr+=2; + else + dp->val.u64 = *((uint64_t*)a_ov ), a_ov+=2, gpr=5; + break; + case nsXPTType::T_FLOAT : + if (fpr < 2) + dp->val.f = *((float*) a_fpr), a_fpr++, fpr++; + else + dp->val.f = *((float*) a_ov ), a_ov++; + break; + case nsXPTType::T_DOUBLE : + if (fpr < 2) + dp->val.d = *((double*) a_fpr), a_fpr++, fpr++; + else + dp->val.d = *((double*) a_ov ), a_ov+=2; + break; + case nsXPTType::T_BOOL : + if (gpr < 5) + dp->val.b = *((uint32_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.b = *((uint32_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_CHAR : + if (gpr < 5) + dp->val.c = *((uint32_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.c = *((uint32_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_WCHAR : + if (gpr < 5) + dp->val.wc = *((uint32_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.wc = *((uint32_t*)a_ov ), a_ov++; + break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + uint32_t a_gpr[4]; \ + uint64_t a_fpr[2]; \ + uint32_t *a_ov; \ + \ + __asm__ __volatile__ \ + ( \ + "l %0,0(15)\n\t" \ + "ahi %0,96\n\t" \ + "stm 3,6,0(%3)\n\t" \ + "std 0,%1\n\t" \ + "std 2,%2\n\t" \ + : "=&a" (a_ov), \ + "=m" (a_fpr[0]), \ + "=m" (a_fpr[1]) \ + : "a" (a_gpr) \ + : "memory", "cc", \ + "3", "4", "5", "6" \ + ); \ + \ + return PrepareAndDispatch(this, n, a_gpr, a_fpr, a_ov); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp new file mode 100644 index 0000000000..75ecd83795 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp @@ -0,0 +1,182 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +static nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, + uint64_t* a_gpr, uint64_t *a_fpr, uint64_t *a_ov) +{ + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no info"); + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint32_t gpr = 1, fpr = 0; + + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (gpr < 5) + a_gpr++, gpr++; + else + a_ov++; + } + + if(param.IsOut() || !type.IsArithmetic()) + { + if (gpr < 5) + dp->val.p = (void*) *a_gpr++, gpr++; + else + dp->val.p = (void*) *a_ov++; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : + if (gpr < 5) + dp->val.i8 = *((int64_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i8 = *((int64_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_I16 : + if (gpr < 5) + dp->val.i16 = *((int64_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i16 = *((int64_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_I32 : + if (gpr < 5) + dp->val.i32 = *((int64_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i32 = *((int64_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_I64 : + if (gpr < 5) + dp->val.i64 = *((int64_t*) a_gpr), a_gpr++, gpr++; + else + dp->val.i64 = *((int64_t*) a_ov ), a_ov++; + break; + case nsXPTType::T_U8 : + if (gpr < 5) + dp->val.u8 = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u8 = *((uint64_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_U16 : + if (gpr < 5) + dp->val.u16 = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u16 = *((uint64_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_U32 : + if (gpr < 5) + dp->val.u32 = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u32 = *((uint64_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_U64 : + if (gpr < 5) + dp->val.u64 = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.u64 = *((uint64_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_FLOAT : + if (fpr < 4) + dp->val.f = *((float*) a_fpr), a_fpr++, fpr++; + else + dp->val.f = *(((float*) a_ov )+1), a_ov++; + break; + case nsXPTType::T_DOUBLE : + if (fpr < 4) + dp->val.d = *((double*) a_fpr), a_fpr++, fpr++; + else + dp->val.d = *((double*) a_ov ), a_ov++; + break; + case nsXPTType::T_BOOL : + if (gpr < 5) + dp->val.b = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.b = *((uint64_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_CHAR : + if (gpr < 5) + dp->val.c = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.c = *((uint64_t*)a_ov ), a_ov++; + break; + case nsXPTType::T_WCHAR : + if (gpr < 5) + dp->val.wc = *((uint64_t*)a_gpr), a_gpr++, gpr++; + else + dp->val.wc = *((uint64_t*)a_ov ), a_ov++; + break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + uint64_t a_gpr[4]; \ + uint64_t a_fpr[4]; \ + uint64_t *a_ov; \ + \ + __asm__ __volatile__ \ + ( \ + "lg %0,0(15)\n\t" \ + "aghi %0,160\n\t" \ + "stmg 3,6,0(%5)\n\t"\ + "std 0,%1\n\t" \ + "std 2,%2\n\t" \ + "std 4,%3\n\t" \ + "std 6,%4\n\t" \ + : "=&a" (a_ov), \ + "=m" (a_fpr[0]), \ + "=m" (a_fpr[1]), \ + "=m" (a_fpr[2]), \ + "=m" (a_fpr[3]) \ + : "a" (a_gpr) \ + : "memory", "cc", \ + "3", "4", "5", "6" \ + ); \ + \ + return PrepareAndDispatch(this, n, a_gpr, a_fpr, a_ov); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_loongarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_loongarch64.cpp new file mode 100644 index 0000000000..02ba47d134 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_loongarch64.cpp @@ -0,0 +1,159 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, V. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" + +extern "C" nsresult ATTRIBUTE_USED PrepareAndDispatch(nsXPTCStubBase* self, + uint32_t methodIndex, + uint64_t* args, + uint64_t* gpregs, + double* fpregs) { + static const uint32_t GPR_COUNT = 8; + static const uint32_t FPR_COUNT = 8; + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + + uint32_t paramCount = info->GetParamCount(); + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint64_t* ap = args; + uint32_t nr_gpr = 1; // skip the arg which is 'self' + uint32_t nr_fpr = 0; + uint64_t value; + + for (uint32_t i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (nr_gpr < GPR_COUNT) + nr_gpr++; + else + ap++; + } + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) { + dp->val.d = fpregs[nr_fpr++]; + } else if (nr_gpr < GPR_COUNT) { + memcpy(&dp->val.d, &gpregs[nr_gpr++], sizeof(dp->val.d)); + } else { + memcpy(&dp->val.d, ap++, sizeof(dp->val.d)); + } + continue; + } + + if (!param.IsOut() && type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) { + memcpy(&dp->val.f, &fpregs[nr_fpr++], sizeof(dp->val.f)); + } else if (nr_gpr < GPR_COUNT) { + memcpy(&dp->val.f, &gpregs[nr_gpr++], sizeof(dp->val.f)); + } else { + memcpy(&dp->val.f, ap++, sizeof(dp->val.f)); + } + continue; + } + + if (nr_gpr < GPR_COUNT) { + value = gpregs[nr_gpr++]; + } else { + value = *ap++; + } + + if (param.IsOut() || !type.IsArithmetic()) { + dp->val.p = (void*)value; + continue; + } + + switch (type) { + case nsXPTType::T_I8: + dp->val.i8 = (int8_t)value; + break; + case nsXPTType::T_I16: + dp->val.i16 = (int16_t)value; + break; + case nsXPTType::T_I32: + dp->val.i32 = (int32_t)value; + break; + case nsXPTType::T_I64: + dp->val.i64 = (int64_t)value; + break; + case nsXPTType::T_U8: + dp->val.u8 = (uint8_t)value; + break; + case nsXPTType::T_U16: + dp->val.u16 = (uint16_t)value; + break; + case nsXPTType::T_U32: + dp->val.u32 = (uint32_t)value; + break; + case nsXPTType::T_U64: + dp->val.u64 = (uint64_t)value; + break; + case nsXPTType::T_BOOL: + dp->val.b = (bool)(uint8_t)value; + break; + case nsXPTType::T_CHAR: + dp->val.c = (char)value; + break; + case nsXPTType::T_WCHAR: + dp->val.wc = (wchar_t)value; + break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + return result; +} + +// Load $t6 with the constant 'n' and branch to SharedStub(). +// clang-format off +#define STUB_ENTRY(n) \ + __asm__( \ + ".text\n\t" \ + ".if "#n" < 10 \n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".hidden _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ + "_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + ".elseif "#n" < 100 \n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".hidden _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ + "_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + ".elseif "#n" < 1000 \n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".hidden _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ + "_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + ".else \n\t" \ + ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ + ".endif \n\t" \ + "li.d $t6, "#n" \n\t" \ + "b SharedStub \n" \ + ".if "#n" < 10 \n\t" \ + ".size _ZN14nsXPTCStubBase5Stub"#n"Ev,.-_ZN14nsXPTCStubBase5Stub"#n"Ev\n\t" \ + ".elseif "#n" < 100 \n\t" \ + ".size _ZN14nsXPTCStubBase6Stub"#n"Ev,.-_ZN14nsXPTCStubBase6Stub"#n"Ev\n\t" \ + ".else \n\t" \ + ".size _ZN14nsXPTCStubBase7Stub"#n"Ev,.-_ZN14nsXPTCStubBase7Stub"#n"Ev\n\t" \ + ".endif" \ +); +// clang-format on + +#define SENTINEL_ENTRY(n) \ + nsresult nsXPTCStubBase::Sentinel##n() { \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ + } + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp new file mode 100644 index 0000000000..7e686b2b08 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp @@ -0,0 +1,104 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * Version: MPL 1.1 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" + +#include <stdint.h> + +/* + * This is for MIPS O32 ABI + * Args contains a0-3 and then the stack. + * Because a0 is 'this', we want to skip it + */ +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ + args++; // always skip over a0 + + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) + ap++; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + + switch(type) + { + case nsXPTType::T_I64 : + if ((intptr_t)ap & 4) ap++; + dp->val.i64 = *((int64_t*) ap); ap++; + break; + case nsXPTType::T_U64 : + if ((intptr_t)ap & 4) ap++; + dp->val.u64 = *((int64_t*) ap); ap++; + break; + case nsXPTType::T_DOUBLE: + if ((intptr_t)ap & 4) ap++; + dp->val.d = *((double*) ap); ap++; + break; +#ifdef IS_LITTLE_ENDIAN + default: + dp->val.p = (void*) *ap; + break; +#else + case nsXPTType::T_I8 : dp->val.i8 = (int8_t) *ap; break; + case nsXPTType::T_I16 : dp->val.i16 = (int16_t) *ap; break; + case nsXPTType::T_I32 : dp->val.i32 = (int32_t) *ap; break; + case nsXPTType::T_U8 : dp->val.u8 = (uint8_t) *ap; break; + case nsXPTType::T_U16 : dp->val.u16 = (uint16_t) *ap; break; + case nsXPTType::T_U32 : dp->val.u32 = (uint32_t) *ap; break; + case nsXPTType::T_BOOL : dp->val.b = (bool) *ap; break; + case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break; + case nsXPTType::T_WCHAR : dp->val.wc = (wchar_t) *ap; break; + case nsXPTType::T_FLOAT : dp->val.f = *(float *) ap; break; + default: + NS_ASSERTION(0, "bad type"); + break; +#endif + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +#define STUB_ENTRY(n) // done in the .s file + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp new file mode 100644 index 0000000000..0c2bdcdcbb --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp @@ -0,0 +1,183 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" + +#if (_MIPS_SIM != _ABIN32) && (_MIPS_SIM != _ABI64) +#error "This code is for MIPS n32/n64 only" +#endif + +/* + * This is for MIPS n32/n64 ABI + * + * When we're called, the "gp" registers are stored in gprData and + * the "fp" registers are stored in fprData. There are 8 regs + * available which correspond to the first 7 parameters of the + * function and the "this" pointer. If there are additional parms, + * they are stored on the stack at address "args". + * + */ +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args, + uint64_t *gprData, double *fprData) +{ +#define PARAM_GPR_COUNT 7 +#define PARAM_FPR_COUNT 7 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint64_t* ap = args; + uint32_t iCount = 0; + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (iCount < PARAM_GPR_COUNT) + iCount++; + else + ap++; + } + + if(param.IsOut() || !type.IsArithmetic()) + { + if (iCount < PARAM_GPR_COUNT) + dp->val.p = (void*)gprData[iCount++]; + else + dp->val.p = (void*)*ap++; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8: + if (iCount < PARAM_GPR_COUNT) + dp->val.i8 = (int8_t)gprData[iCount++]; + else + dp->val.i8 = (int8_t)*ap++; + break; + + case nsXPTType::T_I16: + if (iCount < PARAM_GPR_COUNT) + dp->val.i16 = (int16_t)gprData[iCount++]; + else + dp->val.i16 = (int16_t)*ap++; + break; + + case nsXPTType::T_I32: + if (iCount < PARAM_GPR_COUNT) + dp->val.i32 = (int32_t)gprData[iCount++]; + else + dp->val.i32 = (int32_t)*ap++; + break; + + case nsXPTType::T_I64: + if (iCount < PARAM_GPR_COUNT) + dp->val.i64 = (int64_t)gprData[iCount++]; + else + dp->val.i64 = (int64_t)*ap++; + break; + + case nsXPTType::T_U8: + if (iCount < PARAM_GPR_COUNT) + dp->val.u8 = (uint8_t)gprData[iCount++]; + else + dp->val.u8 = (uint8_t)*ap++; + break; + + case nsXPTType::T_U16: + if (iCount < PARAM_GPR_COUNT) + dp->val.u16 = (uint16_t)gprData[iCount++]; + else + dp->val.u16 = (uint16_t)*ap++; + break; + + case nsXPTType::T_U32: + if (iCount < PARAM_GPR_COUNT) + dp->val.u32 = (uint32_t)gprData[iCount++]; + else + dp->val.u32 = (uint32_t)*ap++; + break; + + case nsXPTType::T_U64: + if (iCount < PARAM_GPR_COUNT) + dp->val.u64 = (uint64_t)gprData[iCount++]; + else + dp->val.u64 = (uint64_t)*ap++; + break; + + case nsXPTType::T_FLOAT: + // the float data formate must not be converted! + // Just only copy without conversion. + if (iCount < PARAM_FPR_COUNT) + dp->val.f = *(float*)&fprData[iCount++]; + else + dp->val.f = *((float*)ap++); + break; + + case nsXPTType::T_DOUBLE: + if (iCount < PARAM_FPR_COUNT) + dp->val.d = (double)fprData[iCount++]; + else + dp->val.d = *((double*)ap++); + break; + + case nsXPTType::T_BOOL: + if (iCount < PARAM_GPR_COUNT) + dp->val.b = (bool)gprData[iCount++]; + else + dp->val.b = (bool)*ap++; + break; + + case nsXPTType::T_CHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.c = (char)gprData[iCount++]; + else + dp->val.c = (char)*ap++; + break; + + case nsXPTType::T_WCHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.wc = (wchar_t)gprData[iCount++]; + else + dp->val.wc = (wchar_t)*ap++; + break; + + default: + NS_ASSERTION(0, "bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +#define STUB_ENTRY(n) /* defined in the assembly file */ + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp new file mode 100644 index 0000000000..f833a7d902 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp @@ -0,0 +1,141 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +#if _HPUX +#error "This code is for HP-PA RISC 32 bit mode only" +#endif + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, + uint32_t* args, uint32_t* floatargs) +{ + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; + + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + int32_t regwords = 1; /* self pointer is not in the variant records */ + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (!info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + for(i = 0; i < paramCount; ++i, --args) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + MOZ_CRASH("NYI: support implicit JSContext*, bug 1475699"); + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *args; + ++regwords; + continue; + } + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) args); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) args); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) args); break; + case nsXPTType::T_DOUBLE : + if (regwords & 1) + { + ++regwords; /* align on double word */ + --args; + } + if (regwords == 0 || regwords == 2) + { + dp->val.d=*((double*) (floatargs + regwords)); + --args; + } + else + { + dp->val.d = *((double*) --args); + } + regwords += 2; + continue; + case nsXPTType::T_U64 : + case nsXPTType::T_I64 : + if (regwords & 1) + { + ++regwords; /* align on double word */ + --args; + } + ((DU *)dp)->lo = *((uint32_t*) args); + ((DU *)dp)->hi = *((uint32_t*) --args); + regwords += 2; + continue; + case nsXPTType::T_FLOAT : + if (regwords >= 4) + dp->val.f = *((float*) args); + else + dp->val.f = *((float*) floatargs+4+regwords); + break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*) args); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*) args); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*) args); break; + case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*) args); break; + case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*) args); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) args); break; + default: + NS_ERROR("bad type"); + break; + } + ++regwords; + } + + nsresult result = self->mOuter->CallMethod((uint16_t) methodIndex, info, + paramBuffer); + + return result; +} + +extern "C" nsresult SharedStub(int); + +#ifdef __GNUC__ +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + /* Save arg0 in its stack slot. This assumes the frame size is 64. */ \ + __asm__ __volatile__ ("STW %r26, -36-64(%sp)"); \ + return SharedStub(n); \ +} +#else +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + return SharedStub(n); \ +} +#endif + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp new file mode 100644 index 0000000000..5bbb6f9e5f --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp @@ -0,0 +1,280 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Implement shared vtbl methods. + +#include "xptcprivate.h" + +// Prior to POWER8, all 64-bit Power ISA systems used ELF v1 ABI, found +// here: +// https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html +// and in particular: +// https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-CALL +// Little-endian ppc64le, however, uses ELF v2 ABI, which is here: +// http://openpowerfoundation.org/wp-content/uploads/resources/leabi/leabi-20170510.pdf +// and in particular section 2.2, page 22. However, most big-endian ppc64 +// systems still use ELF v1, so this file should support both. +// +// Both ABIs pass the first 8 integral parameters and the first 13 floating +// point parameters in registers r3-r10 and f1-f13. No stack space is +// allocated for these by the caller. The rest of the parameters are passed +// in the caller's stack area. The stack pointer must stay 16-byte aligned. + +const uint32_t GPR_COUNT = 7; +const uint32_t FPR_COUNT = 13; + +// PrepareAndDispatch() is called by SharedStub() and calls the actual method. +// +// - 'args[]' contains the arguments passed on stack +// - 'gpregs[]' contains the arguments passed in integer registers +// - 'fpregs[]' contains the arguments passed in floating point registers +// +// The parameters are mapped into an array of type 'nsXPTCMiniVariant' +// and then the method gets called. +// +// Both ABIs use the same register assignment strategy, as per this +// example from V1 ABI section 3.2.3 and V2 ABI section 2.2.3.2 [page 43]: +// +// typedef struct { +// int a; +// double dd; +// } sparm; +// sparm s, t; +// int c, d, e; +// long double ld; +// double ff, gg, hh; +// +// x = func(c, ff, d, ld, s, gg, t, e, hh); +// +// Parameter Register Offset in parameter save area +// c r3 0-7 (not stored in parameter save area) +// ff f1 8-15 (not stored) +// d r5 16-23 (not stored) +// ld f2,f3 24-39 (not stored) +// s r8,r9 40-55 (not stored) +// gg f4 56-63 (not stored) +// t (none) 64-79 (stored in parameter save area) +// e (none) 80-87 (stored) +// hh f5 88-95 (not stored) +// +// i.e., each successive FPR usage skips a GPR, but not the other way around. + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex, + uint64_t * args, uint64_t * gpregs, double *fpregs) +{ + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint32_t paramCount; + uint32_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (!info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint64_t* ap = args; + // |that| is implicit in the calling convention; we really do start at the + // first GPR (as opposed to x86_64). + uint32_t nr_gpr = 0; + uint32_t nr_fpr = 0; + uint64_t value; + + for(i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (nr_gpr < GPR_COUNT) + nr_gpr++; + else + ap++; + } + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) { + dp->val.d = fpregs[nr_fpr++]; + // Even if we have enough FPRs, still skip space in + // the parameter area if we ran out of placeholder GPRs. + if (nr_gpr < GPR_COUNT) { + nr_gpr++; + } else { + ap++; + } + } else { + dp->val.d = *(double*)ap++; + } + continue; + } + if (!param.IsOut() && type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) { + // Single-precision floats are passed in FPRs too. + dp->val.f = (float)fpregs[nr_fpr++]; + if (nr_gpr < GPR_COUNT) { + nr_gpr++; + } else { + ap++; + } + } else { +#ifdef __LITTLE_ENDIAN__ + dp->val.f = *(float*)ap++; +#else + // Big endian needs adjustment to point to the least + // significant word. + float* p = (float*)ap; + p++; + dp->val.f = *p; + ap++; +#endif + } + continue; + } + if (nr_gpr < GPR_COUNT) + value = gpregs[nr_gpr++]; + else + value = *ap++; + + if (param.IsOut() || !type.IsArithmetic()) { + dp->val.p = (void*) value; + continue; + } + + switch (type) { + case nsXPTType::T_I8: dp->val.i8 = (int8_t) value; break; + case nsXPTType::T_I16: dp->val.i16 = (int16_t) value; break; + case nsXPTType::T_I32: dp->val.i32 = (int32_t) value; break; + case nsXPTType::T_I64: dp->val.i64 = (int64_t) value; break; + case nsXPTType::T_U8: dp->val.u8 = (uint8_t) value; break; + case nsXPTType::T_U16: dp->val.u16 = (uint16_t) value; break; + case nsXPTType::T_U32: dp->val.u32 = (uint32_t) value; break; + case nsXPTType::T_U64: dp->val.u64 = (uint64_t) value; break; + case nsXPTType::T_BOOL: dp->val.b = (bool) value; break; + case nsXPTType::T_CHAR: dp->val.c = (char) value; break; + case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break; + + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t) methodIndex, info, + paramBuffer); + + return result; +} + +// Load r11 with the constant 'n' and branch to SharedStub(). +// +// As G++3 ABI contains the length of the functionname in the mangled +// name, it is difficult to get a generic assembler mechanism like +// in the G++ 2.95 case. +// XXX Yes, it's ugly that we're relying on gcc's name-mangling here; +// however, it's quick, dirty, and'll break when the ABI changes on +// us, which is what we want ;-). +// Create names would be like: +// _ZN14nsXPTCStubBase5Stub1Ev +// _ZN14nsXPTCStubBase6Stub12Ev +// _ZN14nsXPTCStubBase7Stub123Ev +// _ZN14nsXPTCStubBase8Stub1234Ev +// etc. +// Use assembler directives to get the names right. + +#if _CALL_ELF == 2 +# define STUB_ENTRY(n) \ +__asm__ ( \ + ".section \".text\" \n\t" \ + ".align 2 \n\t" \ + ".if "#n" < 10 \n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + "0: addis 2,12,.TOC.-0b@ha \n\t" \ + "addi 2,2,.TOC.-0b@l \n\t" \ + ".localentry _ZN14nsXPTCStubBase5Stub"#n"Ev,.-_ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + \ + ".elseif "#n" < 100 \n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + "0: addis 2,12,.TOC.-0b@ha \n\t" \ + "addi 2,2,.TOC.-0b@l \n\t" \ + ".localentry _ZN14nsXPTCStubBase6Stub"#n"Ev,.-_ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + \ + ".elseif "#n" < 1000 \n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + "0: addis 2,12,.TOC.-0b@ha \n\t" \ + "addi 2,2,.TOC.-0b@l \n\t" \ + ".localentry _ZN14nsXPTCStubBase7Stub"#n"Ev,.-_ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + \ + ".else \n\t" \ + ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ + ".endif \n\t" \ + \ + "li 11,"#n" \n\t" \ + "b SharedStub \n" \ +); +#else +# define STUB_ENTRY(n) \ +__asm__ ( \ + ".section \".toc\",\"aw\" \n\t" \ + ".section \".text\" \n\t" \ + ".align 2 \n\t" \ + ".if "#n" < 10 \n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".section \".opd\",\"aw\" \n\t" \ + ".align 3 \n\t" \ +"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + ".quad ._ZN14nsXPTCStubBase5Stub"#n"Ev,.TOC.@tocbase \n\t" \ + ".previous \n\t" \ + ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ +"._ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + \ + ".elseif "#n" < 100 \n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".section \".opd\",\"aw\" \n\t" \ + ".align 3 \n\t" \ +"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + ".quad ._ZN14nsXPTCStubBase6Stub"#n"Ev,.TOC.@tocbase \n\t" \ + ".previous \n\t" \ + ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ +"._ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + \ + ".elseif "#n" < 1000 \n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".section \".opd\",\"aw\" \n\t" \ + ".align 3 \n\t" \ +"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + ".quad ._ZN14nsXPTCStubBase7Stub"#n"Ev,.TOC.@tocbase \n\t" \ + ".previous \n\t" \ + ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ +"._ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + \ + ".else \n\t" \ + ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ + ".endif \n\t" \ + \ + "li 11,"#n" \n\t" \ + "b SharedStub \n" \ +); +#endif + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp new file mode 100644 index 0000000000..28eee7c394 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp @@ -0,0 +1,181 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +#if defined(AIX) + +/* + For PPC (AIX & MAC), the first 8 integral and the first 13 f.p. parameters + arrive in a separate chunk of data that has been loaded from the registers. + The args pointer has been set to the start of the parameters BEYOND the ones + arriving in registers +*/ +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args, uint32_t *gprData, double *fprData) +{ + typedef struct { + uint32_t hi; + uint32_t lo; // have to move 64 bit entities as 32 bit halves since + } DU; // stack slots are not guaranteed 16 byte aligned + +#define PARAM_GPR_COUNT 7 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info = nullptr; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint32_t* ap = args; + uint32_t iCount = 0; + uint32_t fpCount = 0; + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (iCount < PARAM_GPR_COUNT) + iCount++; + else + ap++; + } + + if(param.IsOut() || !type.IsArithmetic()) + { + if (iCount < PARAM_GPR_COUNT) + dp->val.p = (void*) gprData[iCount++]; + else + dp->val.p = (void*) *ap++; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT) + dp->val.i8 = (int8_t) gprData[iCount++]; + else + dp->val.i8 = (int8_t) *ap++; + break; + case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT) + dp->val.i16 = (int16_t) gprData[iCount++]; + else + dp->val.i16 = (int16_t) *ap++; + break; + case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT) + dp->val.i32 = (int32_t) gprData[iCount++]; + else + dp->val.i32 = (int32_t) *ap++; + break; + case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT) + ((DU *)dp)->hi = (int32_t) gprData[iCount++]; + else + ((DU *)dp)->hi = (int32_t) *ap++; + if (iCount < PARAM_GPR_COUNT) + ((DU *)dp)->lo = (uint32_t) gprData[iCount++]; + else + ((DU *)dp)->lo = (uint32_t) *ap++; + break; + case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT) + dp->val.u8 = (uint8_t) gprData[iCount++]; + else + dp->val.u8 = (uint8_t) *ap++; + break; + case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT) + dp->val.u16 = (uint16_t) gprData[iCount++]; + else + dp->val.u16 = (uint16_t) *ap++; + break; + case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT) + dp->val.u32 = (uint32_t) gprData[iCount++]; + else + dp->val.u32 = (uint32_t) *ap++; + break; + case nsXPTType::T_U64 : if (iCount < PARAM_GPR_COUNT) + ((DU *)dp)->hi = (uint32_t) gprData[iCount++]; + else + ((DU *)dp)->hi = (uint32_t) *ap++; + if (iCount < PARAM_GPR_COUNT) + ((DU *)dp)->lo = (uint32_t) gprData[iCount++]; + else + ((DU *)dp)->lo = (uint32_t) *ap++; + break; + case nsXPTType::T_FLOAT : if (fpCount < 13) { + dp->val.f = (float) fprData[fpCount++]; + if (iCount < PARAM_GPR_COUNT) + ++iCount; + else + ++ap; + } + else + dp->val.f = *((float*) ap++); + break; + case nsXPTType::T_DOUBLE : if (fpCount < 13) { + dp->val.d = (double) fprData[fpCount++]; + if (iCount < PARAM_GPR_COUNT) + ++iCount; + else + ++ap; + if (iCount < PARAM_GPR_COUNT) + ++iCount; + else + ++ap; + } + else { + dp->val.f = *((double*) ap); + ap += 2; + } + break; + case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT) + dp->val.b = (bool) gprData[iCount++]; + else + dp->val.b = (bool) *ap++; + break; + case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT) + dp->val.c = (char) gprData[iCount++]; + else + dp->val.c = (char) *ap++; + break; + case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT) + dp->val.wc = (wchar_t) gprData[iCount++]; + else + dp->val.wc = (wchar_t) *ap++; + break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +#define STUB_ENTRY(n) + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +#endif /* AIX */ diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp new file mode 100644 index 0000000000..297ed3e3bb --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp @@ -0,0 +1,168 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +#if defined(AIX) + +/* + For PPC (AIX & MAC), the first 8 integral and the first 13 f.p. parameters + arrive in a separate chunk of data that has been loaded from the registers. + The args pointer has been set to the start of the parameters BEYOND the ones + arriving in registers +*/ +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args, uint64_t *gprData, double *fprData) +{ + +#define PARAM_GPR_COUNT 7 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info = nullptr; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint64_t* ap = args; + uint32_t iCount = 0; + uint32_t fpCount = 0; + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (iCount < PARAM_GPR_COUNT) + iCount++; + else + ap++; + } + + if(param.IsOut() || !type.IsArithmetic()) + { + if (iCount < PARAM_GPR_COUNT) + dp->val.p = (void*) gprData[iCount++]; + else + dp->val.p = (void*) *ap++; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT) + dp->val.i8 = (int8_t) gprData[iCount++]; + else + dp->val.i8 = (int8_t) *ap++; + break; + case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT) + dp->val.i16 = (int16_t) gprData[iCount++]; + else + dp->val.i16 = (int16_t) *ap++; + break; + case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT) + dp->val.i32 = (int32_t) gprData[iCount++]; + else + dp->val.i32 = (int32_t) *ap++; + break; + case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT) + dp->val.i64 = (int64_t) gprData[iCount++]; + else + dp->val.i64 = (int64_t) *ap++; + break; + case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT) + dp->val.u8 = (uint8_t) gprData[iCount++]; + else + dp->val.u8 = (uint8_t) *ap++; + break; + case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT) + dp->val.u16 = (uint16_t) gprData[iCount++]; + else + dp->val.u16 = (uint16_t) *ap++; + break; + case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT) + dp->val.u32 = (uint32_t) gprData[iCount++]; + else + dp->val.u32 = (uint32_t) *ap++; + break; + case nsXPTType::T_U64 : if (iCount < PARAM_GPR_COUNT) + dp->val.u64 = (uint64_t) gprData[iCount++]; + else + dp->val.u64 = (uint64_t) *ap++; + break; + case nsXPTType::T_FLOAT : if (fpCount < 13) { + dp->val.f = (float) fprData[fpCount++]; + if (iCount < PARAM_GPR_COUNT) + ++iCount; + else + ++ap; + } + else + dp->val.f = *((float*) ap++); + break; + case nsXPTType::T_DOUBLE : if (fpCount < 13) { + dp->val.d = (double) fprData[fpCount++]; + if (iCount < PARAM_GPR_COUNT) + ++iCount; + else + ++ap; + if (iCount < PARAM_GPR_COUNT) + ++iCount; + else + ++ap; + } + else { + dp->val.f = *((double*) ap); + ap += 2; + } + break; + case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT) + dp->val.b = (bool) gprData[iCount++]; + else + dp->val.b = (bool) *ap++; + break; + case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT) + dp->val.c = (char) gprData[iCount++]; + else + dp->val.c = (char) *ap++; + break; + case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT) + dp->val.wc = (wchar_t) gprData[iCount++]; + else + dp->val.wc = (wchar_t) *ap++; + break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +#define STUB_ENTRY(n) + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +#endif /* AIX */ diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp new file mode 100644 index 0000000000..e644428f77 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp @@ -0,0 +1,211 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Implement shared vtbl methods. + +#include "xptcprivate.h" + +// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral +// parameters and the first 8 floating point parameters in registers +// (r3-r10 and f1-f8), no stack space is allocated for these by the +// caller. The rest of the parameters are passed in the callers stack +// area. The stack pointer has to retain 16-byte alignment, longlongs +// and doubles are aligned on 8-byte boundaries. +#ifndef __NO_FPRS__ +#define GPR_COUNT 8 +#define FPR_COUNT 8 +#else +#define GPR_COUNT 8 +#endif +// PrepareAndDispatch() is called by SharedStub() and calls the actual method. +// +// - 'args[]' contains the arguments passed on stack +// - 'gprData[]' contains the arguments passed in integer registers +// - 'fprData[]' contains the arguments passed in floating point registers +// +// The parameters are mapped into an array of type 'nsXPTCMiniVariant' +// and then the method gets called. + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, + uint32_t methodIndex, + uint32_t* args, + uint32_t *gprData, + double *fprData) +{ + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info = nullptr; + uint32_t paramCount; + uint32_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (! info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint32_t* ap = args; + uint32_t gpr = 1; // skip one GPR register +#ifndef __NO_FPRS__ + uint32_t fpr = 0; +#endif + uint32_t tempu32; + uint64_t tempu64; + + for(i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (gpr < GPR_COUNT) + gpr++; + else + ap++; + } + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { +#ifndef __NO_FPRS__ + if (fpr < FPR_COUNT) + dp->val.d = fprData[fpr++]; +#else + if (gpr & 1) + gpr++; + if (gpr + 1 < GPR_COUNT) { + dp->val.d = *(double*) &gprData[gpr]; + gpr += 2; + } +#endif + else { + if ((uint32_t) ap & 4) ap++; // doubles are 8-byte aligned on stack + dp->val.d = *(double*) ap; + ap += 2; + } + continue; + } + else if (!param.IsOut() && type == nsXPTType::T_FLOAT) { +#ifndef __NO_FPRS__ + if (fpr < FPR_COUNT) + dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles +#else + if (gpr < GPR_COUNT) + dp->val.f = *(float*) &gprData[gpr++]; +#endif + else + dp->val.f = *(float*) ap++; + continue; + } + else if (!param.IsOut() && (type == nsXPTType::T_I64 + || type == nsXPTType::T_U64)) { + if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6 + if ((gpr + 1) < GPR_COUNT) { + tempu64 = *(uint64_t*) &gprData[gpr]; + gpr += 2; + } + else { + if ((uint32_t) ap & 4) ap++; // longlongs are 8-byte aligned on stack + tempu64 = *(uint64_t*) ap; + ap += 2; + } + } + else { + if (gpr < GPR_COUNT) + tempu32 = gprData[gpr++]; + else + tempu32 = *ap++; + } + + if(param.IsOut() || !type.IsArithmetic()) { + if (type == nsXPTType::T_JSVAL) + dp->val.p = *((void**) tempu32); + else + dp->val.p = (void*) tempu32; + continue; + } + + switch(type) { + case nsXPTType::T_I8: dp->val.i8 = (int8_t) tempu32; break; + case nsXPTType::T_I16: dp->val.i16 = (int16_t) tempu32; break; + case nsXPTType::T_I32: dp->val.i32 = (int32_t) tempu32; break; + case nsXPTType::T_I64: dp->val.i64 = (int64_t) tempu64; break; + case nsXPTType::T_U8: dp->val.u8 = (uint8_t) tempu32; break; + case nsXPTType::T_U16: dp->val.u16 = (uint16_t) tempu32; break; + case nsXPTType::T_U32: dp->val.u32 = (uint32_t) tempu32; break; + case nsXPTType::T_U64: dp->val.u64 = (uint64_t) tempu64; break; + case nsXPTType::T_BOOL: dp->val.b = (bool) tempu32; break; + case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break; + case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break; + + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, + info, + paramBuffer); + + return result; +} + +// Load r11 with the constant 'n' and branch to SharedStub(). +// +// XXX Yes, it's ugly that we're relying on gcc's name-mangling here; +// however, it's quick, dirty, and'll break when the ABI changes on +// us, which is what we want ;-). + +// gcc-3 version +// +// As G++3 ABI contains the length of the functionname in the mangled +// name, it is difficult to get a generic assembler mechanism like +// in the G++ 2.95 case. +// Create names would be like: +// _ZN14nsXPTCStubBase5Stub1Ev +// _ZN14nsXPTCStubBase6Stub12Ev +// _ZN14nsXPTCStubBase7Stub123Ev +// _ZN14nsXPTCStubBase8Stub1234Ev +// etc. +// Use assembler directives to get the names right... + +# define STUB_ENTRY(n) \ +__asm__ ( \ + ".align 2 \n\t" \ + ".if "#n" < 10 \n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + \ + ".elseif "#n" < 100 \n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + \ + ".elseif "#n" < 1000 \n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + \ + ".else \n\t" \ + ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ + ".endif \n\t" \ + \ + "li 11,"#n" \n\t" \ + "b SharedStub@local \n" \ +); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp new file mode 100644 index 0000000000..121ff48556 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp @@ -0,0 +1,194 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Implement shared vtbl methods. + +#include "xptcprivate.h" + +// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral +// parameters and the first 8 floating point parameters in registers +// (r3-r10 and f1-f8), no stack space is allocated for these by the +// caller. The rest of the parameters are passed in the callers stack +// area. The stack pointer has to retain 16-byte alignment, longlongs +// and doubles are aligned on 8-byte boundaries. + +#define GPR_COUNT 8 +#define FPR_COUNT 8 + +// PrepareAndDispatch() is called by SharedStub() and calls the actual method. +// +// - 'args[]' contains the arguments passed on stack +// - 'gprData[]' contains the arguments passed in integer registers +// - 'fprData[]' contains the arguments passed in floating point registers +// +// The parameters are mapped into an array of type 'nsXPTCMiniVariant' +// and then the method gets called. + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, + uint32_t methodIndex, + uint32_t* args, + uint32_t *gprData, + double *fprData) +{ + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info = nullptr; + uint32_t paramCount; + uint32_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (! info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint32_t* ap = args; + uint32_t gpr = 1; // skip one GPR register + uint32_t fpr = 0; + uint32_t tempu32; + uint64_t tempu64; + + for(i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (gpr < GPR_COUNT) + gpr++; + else + ap++; + } + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { + if (fpr < FPR_COUNT) + dp->val.d = fprData[fpr++]; + else { + if ((uint32_t) ap & 4) ap++; // doubles are 8-byte aligned on stack + dp->val.d = *(double*) ap; + ap += 2; + } + continue; + } + else if (!param.IsOut() && type == nsXPTType::T_FLOAT) { + if (fpr < FPR_COUNT) + dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles + else + dp->val.f = *(float*) ap++; + continue; + } + else if (!param.IsOut() && (type == nsXPTType::T_I64 + || type == nsXPTType::T_U64)) { + if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6 + if ((gpr + 1) < GPR_COUNT) { + tempu64 = *(uint64_t*) &gprData[gpr]; + gpr += 2; + } + else { + if ((uint32_t) ap & 4) ap++; // longlongs are 8-byte aligned on stack + tempu64 = *(uint64_t*) ap; + ap += 2; + } + } + else { + if (gpr < GPR_COUNT) + tempu32 = gprData[gpr++]; + else + tempu32 = *ap++; + } + + if(param.IsOut() || !type.IsArithmetic()) { + if (type == nsXPTType::T_JSVAL) + dp->val.p = *((void**) tempu32); + else + dp->val.p = (void*) tempu32; + continue; + } + + switch(type) { + case nsXPTType::T_I8: dp->val.i8 = (int8_t) tempu32; break; + case nsXPTType::T_I16: dp->val.i16 = (int16_t) tempu32; break; + case nsXPTType::T_I32: dp->val.i32 = (int32_t) tempu32; break; + case nsXPTType::T_I64: dp->val.i64 = (int64_t) tempu64; break; + case nsXPTType::T_U8: dp->val.u8 = (uint8_t) tempu32; break; + case nsXPTType::T_U16: dp->val.u16 = (uint16_t) tempu32; break; + case nsXPTType::T_U32: dp->val.u32 = (uint32_t) tempu32; break; + case nsXPTType::T_U64: dp->val.u64 = (uint64_t) tempu64; break; + case nsXPTType::T_BOOL: dp->val.b = (bool) tempu32; break; + case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break; + case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break; + + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, + info, + paramBuffer); + + return result; +} + +// Load r11 with the constant 'n' and branch to SharedStub(). +// +// XXX Yes, it's ugly that we're relying on gcc's name-mangling here; +// however, it's quick, dirty, and'll break when the ABI changes on +// us, which is what we want ;-). + + +// gcc-3 version +// +// As G++3 ABI contains the length of the functionname in the mangled +// name, it is difficult to get a generic assembler mechanism like +// in the G++ 2.95 case. +// Create names would be like: +// _ZN14nsXPTCStubBase5Stub1Ev +// _ZN14nsXPTCStubBase6Stub12Ev +// _ZN14nsXPTCStubBase7Stub123Ev +// _ZN14nsXPTCStubBase8Stub1234Ev +// etc. +// Use assembler directives to get the names right... + +# define STUB_ENTRY(n) \ +__asm__ ( \ + ".align 2 \n\t" \ + ".if "#n" < 10 \n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + \ + ".elseif "#n" < 100 \n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + \ + ".elseif "#n" < 1000 \n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ +"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + \ + ".else \n\t" \ + ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ + ".endif \n\t" \ + \ + "li 11,"#n" \n\t" \ + "b SharedStub@local \n" \ +); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp new file mode 100644 index 0000000000..43b4f029c6 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp @@ -0,0 +1,150 @@ +/* -*- Mode: C -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" + +/* Under the Mac OS X PowerPC ABI, the first 8 integer and 13 floating point + * parameters are delivered in registers and are not on the stack, although + * stack space is allocated for them. The integer parameters are delivered + * in GPRs r3 through r10. The first 8 words of the parameter area on the + * stack shadow these registers. A word will either be in a register or on + * the stack, but not in both. Although the first floating point parameters + * are passed in floating point registers, GPR space and stack space is + * reserved for them as well. + * + * SharedStub has passed pointers to the parameter section of the stack + * and saved copies of the GPRs and FPRs used for parameter passing. We + * don't care about the first parameter (which is delivered here as the self + * pointer), so SharedStub pointed us past that. argsGPR thus points to GPR + * r4 (corresponding to the first argument after the self pointer) and + * argsStack points to the parameter section of the caller's stack frame + * reserved for the same argument. This way, it is possible to reference + * either argsGPR or argsStack with the same index. + * + * Contrary to the assumption made by the previous implementation, the + * Mac OS X PowerPC ABI doesn't impose any special alignment restrictions on + * parameter sections of stacks. Values that are 64 bits wide appear on the + * stack without any special padding. + * + * See also xptcstubs_asm_ppc_darwin.s.m4:_SharedStub. + * + * ABI reference: + * http://developer.apple.com/documentation/DeveloperTools/Conceptual/ + * MachORuntime/PowerPCConventions/chapter_3_section_1.html */ + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch( + nsXPTCStubBase *self, + uint32_t methodIndex, + uint32_t *argsStack, + uint32_t *argsGPR, + double *argsFPR) { +#define PARAM_FPR_COUNT 13 +#define PARAM_GPR_COUNT 7 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo *methodInfo; + uint8_t paramCount; + uint8_t i; + uint32_t argIndex = 0; + uint32_t fprIndex = 0; + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; + + NS_ASSERTION(self, "no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &methodInfo); + NS_ASSERTION(methodInfo, "no method info"); + + paramCount = methodInfo->GetParamCount(); + + for(i = 0; i < paramCount; i++, argIndex++) { + const nsXPTParamInfo ¶m = methodInfo->GetParam(i); + const nsXPTType &type = param.GetType(); + nsXPTCMiniVariant *dp = ¶mBuffer[i]; + uint32_t theParam; + + if(argIndex < PARAM_GPR_COUNT) + theParam = argsGPR[argIndex]; + else + theParam = argsStack[argIndex]; + + if(param.IsOut() || !type.IsArithmetic()) + dp->val.p = (void *) theParam; + else { + switch(type) { + case nsXPTType::T_I8: + dp->val.i8 = (int8_t) theParam; + break; + case nsXPTType::T_I16: + dp->val.i16 = (int16_t) theParam; + break; + case nsXPTType::T_I32: + dp->val.i32 = (int32_t) theParam; + break; + case nsXPTType::T_U8: + dp->val.u8 = (uint8_t) theParam; + break; + case nsXPTType::T_U16: + dp->val.u16 = (uint16_t) theParam; + break; + case nsXPTType::T_U32: + dp->val.u32 = (uint32_t) theParam; + break; + case nsXPTType::T_I64: + case nsXPTType::T_U64: + ((DU *)dp)->hi = (uint32_t) theParam; + if(++argIndex < PARAM_GPR_COUNT) + ((DU *)dp)->lo = (uint32_t) argsGPR[argIndex]; + else + ((DU *)dp)->lo = (uint32_t) argsStack[argIndex]; + break; + case nsXPTType::T_BOOL: + dp->val.b = (bool) theParam; + break; + case nsXPTType::T_CHAR: + dp->val.c = (char) theParam; + break; + case nsXPTType::T_WCHAR: + dp->val.wc = (wchar_t) theParam; + break; + case nsXPTType::T_FLOAT: + if(fprIndex < PARAM_FPR_COUNT) + dp->val.f = (float) argsFPR[fprIndex++]; + else + dp->val.f = *(float *) &argsStack[argIndex]; + break; + case nsXPTType::T_DOUBLE: + if(fprIndex < PARAM_FPR_COUNT) + dp->val.d = argsFPR[fprIndex++]; + else + dp->val.d = *(double *) &argsStack[argIndex]; + argIndex++; + break; + default: + NS_ERROR("bad type"); + break; + } + } + } + + nsresult result = self->mOuter-> + CallMethod((uint16_t)methodIndex, methodInfo, paramBuffer); + + return result; +} + +#define STUB_ENTRY(n) +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_riscv64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_riscv64.cpp new file mode 100644 index 0000000000..b50fc23ffd --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_riscv64.cpp @@ -0,0 +1,160 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#if defined(__riscv_float_abi_soft) +# error "Not support soft float ABI" +#endif + +#include "xptcprivate.h" + +extern "C" nsresult ATTRIBUTE_USED PrepareAndDispatch(nsXPTCStubBase* self, + uint32_t methodIndex, + uint64_t* args, + uint64_t* gpregs, + double* fpregs) { + static const uint32_t GPR_COUNT = 8; + static const uint32_t FPR_COUNT = 8; + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + + uint32_t paramCount = info->GetParamCount(); + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint64_t* ap = args; + uint32_t nr_gpr = 1; // skip one GPR register for 'self' + uint32_t nr_fpr = 0; + uint64_t value; + + for (uint32_t i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (nr_gpr < GPR_COUNT) + nr_gpr++; + else + ap++; + } + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) { + dp->val.d = fpregs[nr_fpr++]; + } else { + dp->val.d = *(double*)ap++; + } + continue; + } + + if (!param.IsOut() && type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) { + dp->val.d = fpregs[nr_fpr++]; + } else { + dp->val.f = *(float*)ap++; + } + continue; + } + + if (nr_gpr < GPR_COUNT) { + value = gpregs[nr_gpr++]; + } else { + value = *ap++; + } + + if (param.IsOut() || !type.IsArithmetic()) { + dp->val.p = (void*)value; + continue; + } + + switch (type) { + case nsXPTType::T_I8: + dp->val.i8 = (int8_t)value; + break; + case nsXPTType::T_I16: + dp->val.i16 = (int16_t)value; + break; + case nsXPTType::T_I32: + dp->val.i32 = (int32_t)value; + break; + case nsXPTType::T_I64: + dp->val.i64 = (int64_t)value; + break; + case nsXPTType::T_U8: + dp->val.u8 = (uint8_t)value; + break; + case nsXPTType::T_U16: + dp->val.u16 = (uint16_t)value; + break; + case nsXPTType::T_U32: + dp->val.u32 = (uint32_t)value; + break; + case nsXPTType::T_U64: + dp->val.u64 = (uint64_t)value; + break; + case nsXPTType::T_BOOL: + dp->val.b = (bool)(uint8_t)value; + break; + case nsXPTType::T_CHAR: + dp->val.c = (char)value; + break; + case nsXPTType::T_WCHAR: + dp->val.wc = (wchar_t)value; + break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = + self->mOuter->CallMethod((uint16_t)methodIndex, info, paramBuffer); + + return result; +} + +// Load t0 with the constant 'n' and branch to SharedStub(). +// clang-format off +#define STUB_ENTRY(n) \ + __asm__( \ + ".text\n\t" \ + ".if "#n" < 10 \n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".hidden _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ + "_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + ".elseif "#n" < 100 \n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".hidden _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ + "_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + ".elseif "#n" < 1000 \n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".hidden _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ + "_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + ".else \n\t" \ + ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ + ".endif \n\t" \ + "li t0, "#n" \n\t" \ + "j SharedStub \n" \ + ".if "#n" < 10\n\t" \ + ".size _ZN14nsXPTCStubBase5Stub"#n"Ev,.-_ZN14nsXPTCStubBase5Stub"#n"Ev\n\t" \ + ".elseif "#n" < 100\n\t" \ + ".size _ZN14nsXPTCStubBase6Stub"#n"Ev,.-_ZN14nsXPTCStubBase6Stub"#n"Ev\n\t" \ + ".else\n\t" \ + ".size _ZN14nsXPTCStubBase7Stub"#n"Ev,.-_ZN14nsXPTCStubBase7Stub"#n"Ev\n\t" \ + ".endif" \ +); +// clang-format on + +#define SENTINEL_ENTRY(n) \ + nsresult nsXPTCStubBase::Sentinel##n() { \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ + } + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp new file mode 100644 index 0000000000..79ecc6ab89 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +#if defined(sparc) || defined(__sparc__) + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args) +{ + + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint64_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) + ap++; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_BOOL : dp->val.b = *((int64_t*) ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((uint64_t*) ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((int64_t*) ap); break; + case nsXPTType::T_I8 : dp->val.i8 = *((int64_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int64_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int64_t*) ap); break; + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint64_t*) ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint64_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint64_t*)ap); break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*) ap); break; + case nsXPTType::T_FLOAT : dp->val.f = ((float*) ap)[1]; break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +extern "C" nsresult SharedStub(int, int*); + +/* + * Avoid GCC stack protector to wipe out input registers since the compiler + * thinks the function takes no arguments. + */ +#ifndef nostackprotector +#define nostackprotector __attribute__((__optimize__("no-stack-protector"))) +#endif + +#define STUB_ENTRY(n) \ +nsresult nostackprotector nsXPTCStubBase::Stub##n() \ +{ \ + int dummy; /* defeat tail-call optimization */ \ + return SharedStub(n, &dummy); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +#endif /* sparc || __sparc__ */ diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp new file mode 100644 index 0000000000..33b839ffa4 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp @@ -0,0 +1,103 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +#if defined(sparc) || defined(__sparc__) + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTInterfaceInfo* iface_info = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->GetInterfaceInfo(&iface_info); + NS_ASSERTION(iface_info,"no interface info"); + + iface_info->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (type == nsXPTType::T_JSVAL) + dp->val.p = *((void**) *ap); + else + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_DOUBLE : + case nsXPTType::T_U64 : + case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi; + ((DU *)dp)->lo = ((DU *)ap)->lo; + ap++; + break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*)ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*)ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*)ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +extern "C" nsresult SharedStub(int, int*); + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + int dummy; /* defeat tail-call optimization */ \ + return SharedStub(n, &dummy); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +#endif /* sparc || __sparc__ */ diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp new file mode 100644 index 0000000000..33b839ffa4 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp @@ -0,0 +1,103 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +#if defined(sparc) || defined(__sparc__) + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTInterfaceInfo* iface_info = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->GetInterfaceInfo(&iface_info); + NS_ASSERTION(iface_info,"no interface info"); + + iface_info->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (type == nsXPTType::T_JSVAL) + dp->val.p = *((void**) *ap); + else + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_DOUBLE : + case nsXPTType::T_U64 : + case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi; + ((DU *)dp)->lo = ((DU *)ap)->lo; + ap++; + break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*)ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*)ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*)ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +extern "C" nsresult SharedStub(int, int*); + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + int dummy; /* defeat tail-call optimization */ \ + return SharedStub(n, &dummy); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +#endif /* sparc || __sparc__ */ diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp new file mode 100644 index 0000000000..488c3e7895 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp @@ -0,0 +1,104 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +#if defined(sparc) || defined(__sparc__) + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) +{ + + typedef struct { + uint32_t hi; + uint32_t lo; + } DU; // have to move 64 bit entities as 32 bit halves since + // stack slots are not guaranteed 16 byte aligned + + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no interface info"); + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) + ap++; + + if(param.IsOut() || !type.IsArithmetic()) + { + if (type == nsXPTType::T_JSVAL) + dp->val.p = *((void**) *ap); + else + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_DOUBLE : + case nsXPTType::T_U64 : + case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi; + ((DU *)dp)->lo = ((DU *)ap)->lo; + ap++; + break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*)ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*)ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*)ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +extern "C" nsresult SharedStub(int, int*); + +#define STUB_ENTRY(n) \ +nsresult nsXPTCStubBase::Stub##n() \ +{ \ + int dummy; /* defeat tail-call optimization */ \ + return SharedStub(n, &dummy); \ +} + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +#endif /* sparc || __sparc__ */ diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp new file mode 100644 index 0000000000..48beb32aff --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp @@ -0,0 +1,183 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Implement shared vtbl methods. + +// Keep this in sync with the linux version. + +#include "xptcprivate.h" + +// The Darwin/x86-64 ABI passes the first 6 integer parameters and the +// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx, +// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the +// caller. The rest of the parameters are passed in the callers stack +// area. + +const uint32_t GPR_COUNT = 6; +const uint32_t FPR_COUNT = 8; + +// PrepareAndDispatch() is called by SharedStub() and calls the actual method. +// +// - 'args[]' contains the arguments passed on stack +// - 'gpregs[]' contains the arguments passed in integer registers +// - 'fpregs[]' contains the arguments passed in floating point registers +// +// The parameters are mapped into an array of type 'nsXPTCMiniVariant' +// and then the method gets called. + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex, + uint64_t * args, uint64_t * gpregs, double *fpregs) +{ + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint32_t paramCount; + uint32_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (!info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint64_t* ap = args; + uint32_t nr_gpr = 1; // skip one GPR register for 'that' + uint32_t nr_fpr = 0; + uint64_t value; + + for (i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (nr_gpr < GPR_COUNT) + nr_gpr++; + else + ap++; + } + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) + dp->val.d = fpregs[nr_fpr++]; + else + dp->val.d = *(double*) ap++; + continue; + } + else if (!param.IsOut() && type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) + // The value in %xmm register is already prepared to + // be retrieved as a float. Therefore, we pass the + // value verbatim, as a double without conversion. + dp->val.d = fpregs[nr_fpr++]; + else + dp->val.f = *(float*) ap++; + continue; + } + else { + if (nr_gpr < GPR_COUNT) + value = gpregs[nr_gpr++]; + else + value = *ap++; + } + + if (param.IsOut() || !type.IsArithmetic()) { + dp->val.p = (void*) value; + continue; + } + + switch (type) { + case nsXPTType::T_I8: dp->val.i8 = (int8_t) value; break; + case nsXPTType::T_I16: dp->val.i16 = (int16_t) value; break; + case nsXPTType::T_I32: dp->val.i32 = (int32_t) value; break; + case nsXPTType::T_I64: dp->val.i64 = (int64_t) value; break; + case nsXPTType::T_U8: dp->val.u8 = (uint8_t) value; break; + case nsXPTType::T_U16: dp->val.u16 = (uint16_t) value; break; + case nsXPTType::T_U32: dp->val.u32 = (uint32_t) value; break; + case nsXPTType::T_U64: dp->val.u64 = (uint64_t) value; break; + // Cast to uint8_t first, to remove garbage on upper 56 bits. + case nsXPTType::T_BOOL: dp->val.b = (bool)(uint8_t) value; break; + case nsXPTType::T_CHAR: dp->val.c = (char) value; break; + case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break; + + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t) methodIndex, info, + paramBuffer); + + return result; +} + +// Darwin/x86-64 uses gcc >= 4.2 + +#define STUB_ENTRY(n) \ +asm(".section __TEXT,__text\n\t" \ + ".align 3\n\t" \ + ".if " #n " < 10\n\t" \ + ".globl __ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \ + "__ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \ + ".elseif " #n " < 100\n\t" \ + ".globl __ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \ + "__ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \ + ".elseif " #n " < 1000\n\t" \ + ".globl __ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \ + "__ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \ + ".else\n\t" \ + ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \ + ".endif\n\t" \ + "movl $" #n ", %eax\n\t" \ + "jmp SharedStub\n\t"); + +// static nsresult SharedStub(uint32_t methodIndex) +asm(".section __TEXT,__text\n\t" + ".align 3\n\t" + "SharedStub:\n\t" + // make room for gpregs (48), fpregs (64) + "pushq %rbp\n\t" + "movq %rsp,%rbp\n\t" + "subq $112,%rsp\n\t" + // save GP registers + "movq %rdi,-112(%rbp)\n\t" + "movq %rsi,-104(%rbp)\n\t" + "movq %rdx, -96(%rbp)\n\t" + "movq %rcx, -88(%rbp)\n\t" + "movq %r8 , -80(%rbp)\n\t" + "movq %r9 , -72(%rbp)\n\t" + "leaq -112(%rbp),%rcx\n\t" + // save FP registers + "movsd %xmm0,-64(%rbp)\n\t" + "movsd %xmm1,-56(%rbp)\n\t" + "movsd %xmm2,-48(%rbp)\n\t" + "movsd %xmm3,-40(%rbp)\n\t" + "movsd %xmm4,-32(%rbp)\n\t" + "movsd %xmm5,-24(%rbp)\n\t" + "movsd %xmm6,-16(%rbp)\n\t" + "movsd %xmm7, -8(%rbp)\n\t" + "leaq -64(%rbp),%r8\n\t" + // rdi has the 'self' pointer already + "movl %eax,%esi\n\t" + "leaq 16(%rbp),%rdx\n\t" + "call _PrepareAndDispatch\n\t" + "leave\n\t" + "ret\n\t"); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp new file mode 100644 index 0000000000..e392365be4 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp @@ -0,0 +1,209 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Implement shared vtbl methods. + +// Keep this in sync with the darwin version. + +#include "xptcprivate.h" + +// The Linux/x86-64 ABI passes the first 6 integer parameters and the +// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx, +// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the +// caller. The rest of the parameters are passed in the callers stack +// area. + +const uint32_t GPR_COUNT = 6; +const uint32_t FPR_COUNT = 8; + +// PrepareAndDispatch() is called by SharedStub() and calls the actual method. +// +// - 'args[]' contains the arguments passed on stack +// - 'gpregs[]' contains the arguments passed in integer registers +// - 'fpregs[]' contains the arguments passed in floating point registers +// +// The parameters are mapped into an array of type 'nsXPTCMiniVariant' +// and then the method gets called. + +extern "C" nsresult ATTRIBUTE_USED +PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex, + uint64_t * args, uint64_t * gpregs, double *fpregs) +{ + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + uint32_t paramCount; + uint32_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + if (!info) + return NS_ERROR_UNEXPECTED; + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint64_t* ap = args; + uint32_t nr_gpr = 1; // skip one GPR register for 'that' + uint32_t nr_fpr = 0; + uint64_t value; + + for (i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (nr_gpr < GPR_COUNT) + nr_gpr++; + else + ap++; + } + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) + dp->val.d = fpregs[nr_fpr++]; + else + dp->val.d = *(double*)ap++; + continue; + } + if (!param.IsOut() && type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) + // The value in %xmm register is already prepared to + // be retrieved as a float. Therefore, we pass the + // value verbatim, as a double without conversion. + dp->val.d = fpregs[nr_fpr++]; + else + dp->val.f = *(float*)ap++; + continue; + } + if (nr_gpr < GPR_COUNT) + value = gpregs[nr_gpr++]; + else + value = *ap++; + + if (param.IsOut() || !type.IsArithmetic()) { + dp->val.p = (void*) value; + continue; + } + + switch (type) { + case nsXPTType::T_I8: dp->val.i8 = (int8_t) value; break; + case nsXPTType::T_I16: dp->val.i16 = (int16_t) value; break; + case nsXPTType::T_I32: dp->val.i32 = (int32_t) value; break; + case nsXPTType::T_I64: dp->val.i64 = (int64_t) value; break; + case nsXPTType::T_U8: dp->val.u8 = (uint8_t) value; break; + case nsXPTType::T_U16: dp->val.u16 = (uint16_t) value; break; + case nsXPTType::T_U32: dp->val.u32 = (uint32_t) value; break; + case nsXPTType::T_U64: dp->val.u64 = (uint64_t) value; break; + // Cast to uint8_t first, to remove garbage on upper 56 bits. + case nsXPTType::T_BOOL: dp->val.b = (bool)(uint8_t) value; break; + case nsXPTType::T_CHAR: dp->val.c = (char) value; break; + case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break; + + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t) methodIndex, info, + paramBuffer); + + return result; +} + +// Linux/x86-64 uses gcc >= 3.1 +// We don't include .cfi_startproc/endproc directives for the individual stubs +// because there's no extra CFI bits to define beyond the default CIE. +#define STUB_ENTRY(n) \ +asm(".section \".text\"\n\t" \ + ".align 2\n\t" \ + ".if " #n " < 10\n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \ + ".hidden _ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \ + ".type _ZN14nsXPTCStubBase5Stub" #n "Ev,@function\n" \ + "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \ + ".elseif " #n " < 100\n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \ + ".hidden _ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \ + ".type _ZN14nsXPTCStubBase6Stub" #n "Ev,@function\n" \ + "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \ + ".elseif " #n " < 1000\n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \ + ".hidden _ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \ + ".type _ZN14nsXPTCStubBase7Stub" #n "Ev,@function\n" \ + "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \ + ".else\n\t" \ + ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \ + ".endif\n\t" \ + "movl $" #n ", %eax\n\t" \ + "jmp SharedStub\n\t" \ + ".if " #n " < 10\n\t" \ + ".size _ZN14nsXPTCStubBase5Stub" #n "Ev,.-_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \ + ".elseif " #n " < 100\n\t" \ + ".size _ZN14nsXPTCStubBase6Stub" #n "Ev,.-_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \ + ".else\n\t" \ + ".size _ZN14nsXPTCStubBase7Stub" #n "Ev,.-_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \ + ".endif"); + +// static nsresult SharedStub(uint32_t methodIndex) +asm(".section \".text\"\n\t" + ".align 2\n\t" + ".type SharedStub,@function\n\t" + "SharedStub:\n\t" + ".cfi_startproc\n\t" + // make room for gpregs (48), fpregs (64) + "pushq %rbp\n\t" + ".cfi_def_cfa_offset 16\n\t" + ".cfi_offset 6, -16\n\t" + "movq %rsp,%rbp\n\t" + ".cfi_def_cfa_register 6\n\t" + "subq $112,%rsp\n\t" + // save GP registers + "movq %rdi,-112(%rbp)\n\t" + "movq %rsi,-104(%rbp)\n\t" + "movq %rdx, -96(%rbp)\n\t" + "movq %rcx, -88(%rbp)\n\t" + "movq %r8 , -80(%rbp)\n\t" + "movq %r9 , -72(%rbp)\n\t" + ".cfi_offset 5, -24\n\t" // rdi + ".cfi_offset 4, -32\n\t" // rsi + ".cfi_offset 1, -40\n\t" // rdx + ".cfi_offset 2, -48\n\t" // rcx + ".cfi_offset 8, -56\n\t" // r8 + ".cfi_offset 9, -64\n\t" // r9 + "leaq -112(%rbp),%rcx\n\t" + // save FP registers + "movsd %xmm0,-64(%rbp)\n\t" + "movsd %xmm1,-56(%rbp)\n\t" + "movsd %xmm2,-48(%rbp)\n\t" + "movsd %xmm3,-40(%rbp)\n\t" + "movsd %xmm4,-32(%rbp)\n\t" + "movsd %xmm5,-24(%rbp)\n\t" + "movsd %xmm6,-16(%rbp)\n\t" + "movsd %xmm7, -8(%rbp)\n\t" + "leaq -64(%rbp),%r8\n\t" + // rdi has the 'self' pointer already + "movl %eax,%esi\n\t" + "leaq 16(%rbp),%rdx\n\t" + "call PrepareAndDispatch@plt\n\t" + "leave\n\t" + ".cfi_def_cfa 7, 8\n\t" + "ret\n\t" + ".cfi_endproc\n\t" + ".size SharedStub,.-SharedStub"); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/win32/moz.build b/xpcom/reflect/xptcall/md/win32/moz.build new file mode 100644 index 0000000000..8c169135f4 --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/moz.build @@ -0,0 +1,53 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +if CONFIG["TARGET_CPU"] == "x86_64": + if CONFIG["CC_TYPE"] in ("clang", "gcc"): + SOURCES += [ + "xptcinvoke_x86_64.cpp", + "xptcstubs_x86_64_gnu.cpp", + ] + SOURCES += ["xptcinvoke_asm_x86_64_gnu.s"] + else: + SOURCES += ["xptcinvoke_x86_64.cpp", "xptcstubs_x86_64.cpp"] + SOURCES += ["xptcinvoke_asm_x86_64.asm", "xptcstubs_asm_x86_64.asm"] +elif CONFIG["TARGET_CPU"] == "x86": + if CONFIG["CC_TYPE"] in ("clang", "gcc"): + SOURCES += [ + "xptcinvoke_x86_gnu.cpp", + "xptcstubs.cpp", + ] + else: + SOURCES += [ + "xptcinvoke.cpp", + "xptcinvoke_asm_x86_msvc.asm", + "xptcstubs.cpp", + ] + SOURCES["xptcinvoke_asm_x86_msvc.asm"].flags += ["-safeseh"] +elif CONFIG["TARGET_CPU"] == "aarch64": + SOURCES += [ + "xptcinvoke_aarch64.cpp", + "xptcstubs_aarch64.cpp", + ] + asm_files = [ + "xptcinvoke_asm_aarch64.asm", + "xptcstubs_asm_aarch64.asm", + ] + + # make gets confused if the srcdir and objdir files have the same name, so + # we generate different names for the objdir files + for src in asm_files: + obj = src.replace("_asm_aarch64", "") + GeneratedFile( + obj, script="preprocess.py", entry_point="preprocess", inputs=[src] + ) + SOURCES += ["!%s" % obj] + +FINAL_LIBRARY = "xul" + +LOCAL_INCLUDES += [ + "../..", +] diff --git a/xpcom/reflect/xptcall/md/win32/preprocess.py b/xpcom/reflect/xptcall/md/win32/preprocess.py new file mode 100644 index 0000000000..a2f3232c34 --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/preprocess.py @@ -0,0 +1,44 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import errno +import os +import shlex +import subprocess +import sys +import tempfile + +import buildconfig +from mozfile import which + + +def preprocess(out, asm_file): + cxx = shlex.split(buildconfig.substs["CXX"]) + if not os.path.exists(cxx[0]): + tool = cxx[0] + cxx[0] = which(tool) + if not cxx[0]: + raise OSError(errno.ENOENT, "Could not find {} on PATH.".format(tool)) + + cppflags = buildconfig.substs["OS_CPPFLAGS"] + + # subprocess.Popen(stdout=) only accepts actual file objects, which `out`, + # above, is not. So fake a temporary file to write to. + (outhandle, tmpout) = tempfile.mkstemp(suffix=".cpp") + + # #line directives will confuse armasm64, and /EP is the only way to + # preprocess without emitting #line directives. + command = cxx + ["/EP"] + cppflags + ["/TP", asm_file] + with open(tmpout, "wb") as t: + result = subprocess.Popen(command, stdout=t).wait() + if result != 0: + sys.exit(result) + + with open(tmpout, "rb") as t: + out.write(t.read()) + + os.close(outhandle) + os.remove(tmpout) diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp new file mode 100644 index 0000000000..e4e63edc4b --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp @@ -0,0 +1,45 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#ifndef WIN32 +#error "This code is for Win32 only" +#endif + +extern "C" void __fastcall +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + for(; paramCount > 0; paramCount--, d++, s++) + { + if(s->IsIndirect()) + { + *((void**)d) = &s->val; + continue; + } + switch(s->type) + { + case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; + case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_aarch64.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke_aarch64.cpp new file mode 100644 index 0000000000..1c1860fbeb --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_aarch64.cpp @@ -0,0 +1,141 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +#if !defined(_MSC_VER) && !defined(_M_ARM64) +#error "This code is for AArch64 Windows only" +#endif + +/* "Procedure Call Standard for the ARM 64-bit Architecture" document, sections + * "5.4 Parameter Passing" and "6.1.2 Procedure Calling" contain all the + * needed information. + * + * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf + * + * Windows follows this document, see: + * + * https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions + */ + +/* + * Allocation of integer function arguments initially to registers r1-r7 + * and then to stack. Handling of 'that' argument which goes to register r0 + * is handled separately and does not belong here. + * + * 'ireg_args' - pointer to the current position in the buffer, + * corresponding to the register arguments + * 'stack_args' - pointer to the current position in the buffer, + * corresponding to the arguments on stack + * 'end' - pointer to the end of the registers argument + * buffer. + */ +static inline void alloc_word(uint64_t* &ireg_args, + uint64_t* &stack_args, + uint64_t* end, + uint64_t data) +{ + if (ireg_args < end) { + *ireg_args = data; + ireg_args++; + } else { + *stack_args = data; + stack_args++; + } +} + +static inline void alloc_double(double* &freg_args, + uint64_t* &stack_args, + double* end, + double data) +{ + if (freg_args < end) { + *freg_args = data; + freg_args++; + } else { + memcpy(stack_args, &data, sizeof(data)); + stack_args++; + } +} + +static inline void alloc_float(double* &freg_args, + uint64_t* &stack_args, + double* end, + float data) +{ + if (freg_args < end) { + memcpy(freg_args, &data, sizeof(data)); + freg_args++; + } else { + memcpy(stack_args, &data, sizeof(data)); + stack_args++; + } +} + + +extern "C" void +invoke_copy_to_stack(uint64_t* stk, uint64_t *end, + uint32_t paramCount, nsXPTCVariant* s) +{ + uint64_t *ireg_args = stk; + uint64_t *ireg_end = ireg_args + 8; + double *freg_args = (double *)ireg_end; + double *freg_end = freg_args + 8; + uint64_t *stack_args = (uint64_t *)freg_end; + + // leave room for 'that' argument in x0 + ++ireg_args; + + for (uint32_t i = 0; i < paramCount; i++, s++) { + uint64_t word; + + if (s->IsIndirect()) { + word = (uint64_t)&s->val; + } else { + // According to the ABI, integral types that are smaller than 8 + // bytes are to be passed in 8-byte registers or 8-byte stack + // slots. + switch (s->type) { + case nsXPTType::T_FLOAT: + alloc_float(freg_args, stack_args, freg_end, s->val.f); + continue; + case nsXPTType::T_DOUBLE: + alloc_double(freg_args, stack_args, freg_end, s->val.d); + continue; + case nsXPTType::T_I8: word = s->val.i8; break; + case nsXPTType::T_I16: word = s->val.i16; break; + case nsXPTType::T_I32: word = s->val.i32; break; + case nsXPTType::T_I64: word = s->val.i64; break; + case nsXPTType::T_U8: word = s->val.u8; break; + case nsXPTType::T_U16: word = s->val.u16; break; + case nsXPTType::T_U32: word = s->val.u32; break; + case nsXPTType::T_U64: word = s->val.u64; break; + case nsXPTType::T_BOOL: word = s->val.b; break; + case nsXPTType::T_CHAR: word = s->val.c; break; + case nsXPTType::T_WCHAR: word = s->val.wc; break; + default: + // all the others are plain pointer types + word = reinterpret_cast<uint64_t>(s->val.p); + break; + } + } + + alloc_word(ireg_args, stack_args, ireg_end, word); + } +} + +extern "C" nsresult +XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +extern "C" +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + return XPTC__InvokebyIndex(that, methodIndex, paramCount, params); +} diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_aarch64.asm b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_aarch64.asm new file mode 100644 index 0000000000..21f80f4cb3 --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_aarch64.asm @@ -0,0 +1,66 @@ +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "ksarm64.h" + + IMPORT |invoke_copy_to_stack| + TEXTAREA + +; +;XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex, +; uint32_t paramCount, nsXPTCVariant* params) +; + + NESTED_ENTRY XPTC__InvokebyIndex + + ; set up frame + PROLOG_SAVE_REG_PAIR fp, lr, #-32! + PROLOG_SAVE_REG_PAIR x19, x20, #16 + + ; save methodIndex across function calls + mov w20, w1 + + ; end of stack area passed to invoke_copy_to_stack + mov x1, sp + + ; assume 8 bytes of stack for each argument with 16-byte alignment + add w19, w2, #1 + and w19, w19, #0xfffffffe + sub sp, sp, w19, uxth #3 + + ; temporary place to store args passed in r0-r7,v0-v7 + sub sp, sp, #128 + + ; save 'that' on stack + str x0, [sp] + + ; start of stack area passed to invoke_copy_to_stack + mov x0, sp + bl invoke_copy_to_stack + + ; load arguments passed in r0-r7 + ldp x6, x7, [sp, #48] + ldp x4, x5, [sp, #32] + ldp x2, x3, [sp, #16] + ldp x0, x1, [sp],#64 + + ; load arguments passed in v0-v7 + ldp d6, d7, [sp, #48] + ldp d4, d5, [sp, #32] + ldp d2, d3, [sp, #16] + ldp d0, d1, [sp],#64 + + ; call the method + ldr x16, [x0] + add x16, x16, w20, uxth #3 + ldr x16, [x16] + blr x16 + + EPILOG_STACK_RESTORE + EPILOG_RESTORE_REG_PAIR x19, x20, #16 + EPILOG_RESTORE_REG_PAIR x29, x30, #32! + EPILOG_RETURN + + NESTED_END XPTC__InvokebyIndex + END diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm new file mode 100644 index 0000000000..bf7c2ef0c3 --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm @@ -0,0 +1,107 @@ +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. + +extrn invoke_copy_to_stack:PROC + + +.CODE + +; +;XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex, +; uint32_t paramCount, nsXPTCVariant* params) +; + +XPTC__InvokebyIndex PROC FRAME + + ; store register parameters + + mov qword ptr [rsp+32], r9 ; params + mov dword ptr [rsp+24], r8d ; paramCount + mov dword ptr [rsp+16], edx ; methodIndex + mov qword ptr [rsp+8], rcx ; that + + push rbp + .PUSHREG rbp + mov rbp, rsp ; store current RSP to RBP + .SETFRAME rbp, 0 + .ENDPROLOG + + sub rsp, 32 + + ; maybe we don't have any parameters to copy + + test r8d, r8d + jz noparams + + ; + ; Build stack for stdcall + ; + + ; 1st parameter is space for parameters + + mov eax, r8d + or eax, 1 + shl rax, 3 ; *= 8 + sub rsp, rax + mov rcx, rsp + + ; 2nd parameter is parameter count + + mov edx, r8d + + ; 3rd parameter is params + + mov r8, r9 + + sub rsp, 40 + call invoke_copy_to_stack ; rcx = d + ; edx = paramCount + ; r8 = s + add rsp, 32 + + ; Current stack is the following. + ; + ; 0h: [space (for this)] + ; 8h: [1st parameter] + ; 10h: [2nd parameter] + ; 18h: [3rd parameter] + ; 20h: [4th parameter] + ; ... + ; + ; On Win64 ABI, the first 4 parameters are passed using registers, + ; and others are on stack. + + ; 1st, 2nd and 3rd arguments are passed via registers + + mov rdx, qword ptr [rsp+8] ; 1st parameter + movsd xmm1, qword ptr [rsp+8] ; for double + + mov r8, qword ptr [rsp+16] ; 2nd parameter + movsd xmm2, qword ptr [rsp+16] ; for double + + mov r9, qword ptr [rsp+24] ; 3rd parameter + movsd xmm3, qword ptr [rsp+24] ; for double + + ; rcx register is this + + mov rcx, qword ptr [rbp+8+8] ; that + +noparams: + + ; calculate call address + + mov r11, qword ptr [rcx] + mov eax, dword ptr [rbp+16+8] ; methodIndex + + call qword ptr [r11+rax*8] ; stdcall, i.e. callee cleans up stack. + + mov rsp, rbp + pop rbp + + ret + +XPTC__InvokebyIndex ENDP + + +END diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s new file mode 100644 index 0000000000..5cc19b4c57 --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s @@ -0,0 +1,110 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +.extern invoke_copy_to_stack + + +.text +.intel_syntax noprefix + +# +#_XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex, +# uint32_t paramCount, nsXPTCVariant* params) +# + +.globl XPTC__InvokebyIndex +.def XPTC__InvokebyIndex + .scl 2 + .type 46 +.endef +XPTC__InvokebyIndex: + + # store register parameters + + mov qword ptr [rsp+32], r9 # params + mov dword ptr [rsp+24], r8d # paramCount + mov dword ptr [rsp+16], edx # methodIndex + mov qword ptr [rsp+8], rcx # that + + push rbp + # .PUSHREG rbp + mov rbp, rsp # store current RSP to RBP + # .SETFRAME rbp, 0 + # .ENDPROLOG + + sub rsp, 32 + + # maybe we don't have any parameters to copy + + test r8d, r8d + jz noparams + + # + # Build stack for stdcall + # + + # 1st parameter is space for parameters + + mov eax, r8d + or eax, 1 + shl rax, 3 # *= 8 + sub rsp, rax + mov rcx, rsp + + # 2nd parameter is parameter count + + mov edx, r8d + + # 3rd parameter is params + + mov r8, r9 + + sub rsp, 40 + call invoke_copy_to_stack # rcx = d + # edx = paramCount + # r8 = s + add rsp, 32 + + # Current stack is the following. + # + # 0h: [space (for this)] + # 8h: [1st parameter] + # 10h: [2nd parameter] + # 18h: [3rd parameter] + # 20h: [4th parameter] + # ... + # + # On Win64 ABI, the first 4 parameters are passed using registers, + # and others are on stack. + + # 1st, 2nd and 3rd arguments are passed via registers + + mov rdx, qword ptr [rsp+8] # 1st parameter + movsd xmm1, qword ptr [rsp+8] # for double + + mov r8, qword ptr [rsp+16] # 2nd parameter + movsd xmm2, qword ptr [rsp+16] # for double + + mov r9, qword ptr [rsp+24] # 3rd parameter + movsd xmm3, qword ptr [rsp+24] # for double + + # rcx register is this + + mov rcx, qword ptr [rbp+8+8] # that + +noparams: + + # calculate call address + + mov r11, qword ptr [rcx] + mov eax, dword ptr [rbp+16+8] # methodIndex + + call qword ptr [r11+rax*8] # stdcall, i.e. callee cleans up stack. + + mov rsp, rbp + pop rbp + + ret + + diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm new file mode 100644 index 0000000000..f3b7a1826d --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm @@ -0,0 +1,63 @@ +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. + + TITLE xptcinvoke_asm_x86_msvc.asm + .686P + .model flat + +PUBLIC _NS_InvokeByIndex +EXTRN @invoke_copy_to_stack@12:PROC + +; +; extern "C" nsresult __cdecl +; NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, +; uint32_t paramCount, nsXPTCVariant* params) +; + +_TEXT SEGMENT +_NS_InvokeByIndex PROC + + ; Build frame + push ebp + mov ebp, esp + + ; Save paramCount for later + mov edx, dword ptr [ebp+16] + + ; Do we have any parameters? + test edx, edx + jz noparams + + ; Build call for copy_to_stack, which is __fastcall + + ; Allocate space for parameters. 8 is the biggest size + ; any parameter can be, so assume that all our parameters + ; are that large. + mov eax, edx + shl eax, 3 + sub esp, eax + + mov ecx, esp + push dword ptr [ebp+20] + call @invoke_copy_to_stack@12 +noparams: + ; Push the `this' parameter for the call. + mov ecx, dword ptr [ebp+8] + push ecx + + ; Load the vtable. + mov edx, dword ptr [ecx] + + ; Call the vtable index at `methodIndex'. + mov eax, dword ptr [ebp+12] + call dword ptr [edx+eax*4] + + ; Reset and return. + mov esp, ebp + pop ebp + ret +_NS_InvokeByIndex ENDP +_TEXT ENDS + +END diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp new file mode 100644 index 0000000000..47c891acea --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp @@ -0,0 +1,58 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +extern "C" void +invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s) +{ + for(; paramCount > 0; paramCount--, d++, s++) + { + if(s->IsIndirect()) + { + *((void**)d) = &s->val; + continue; + } + + /* + * AMD64 platform uses 8 bytes align. + */ + + switch(s->type) + { + case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; break; + case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; break; + case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} + +extern "C" nsresult +XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + +extern "C" +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params) +{ + return XPTC__InvokebyIndex(that, methodIndex, paramCount, params); +} diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp new file mode 100644 index 0000000000..7576919b5a --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp @@ -0,0 +1,106 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Platform specific code to invoke XPCOM methods on native objects */ + +#include "xptcprivate.h" + +extern "C" { +void __attribute__ ((__used__)) __attribute__ ((regparm(3))) +invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d) +{ + for(uint32_t i = paramCount; i >0; i--, d++, s++) + { + if(s->IsIndirect()) + { + *((void**)d) = &s->val; + continue; + } + + switch(s->type) + { + case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break; + case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break; + case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; + case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; + case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break; + case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break; + case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; + case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; + case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; + case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; + case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break; + case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break; + case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break; + default: + // all the others are plain pointer types + *((void**)d) = s->val.p; + break; + } + } +} +} // extern "C" + +/* + EXPORT_XPCOM_API(nsresult) + NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); + + Each param takes at most two 4-byte words. + It doesn't matter if we push too many words, and calculating the exact + amount takes time. + + that = ebp + 0x08 + methodIndex = ebp + 0x0c + paramCount = ebp + 0x10 + params = ebp + 0x14 + +*/ + +__asm__ ( + ".text\n\t" +/* alignment here seems unimportant here; this was 16, now it's 2 which + is what xptcstubs uses. */ + ".align 2\n\t" + ".globl _NS_InvokeByIndex\n\t" + "_NS_InvokeByIndex:\n\t" + "pushl %ebp\n\t" + "movl %esp, %ebp\n\t" + "movl 0x10(%ebp), %eax\n\t" + "leal 0(,%eax,8),%edx\n\t" + + /* set up call frame for method. */ + "subl %edx, %esp\n\t" /* make room for params. */ +/* Align to maximum x86 data size: 128 bits == 16 bytes == XMM register size. + * This is to avoid protection faults where SSE+ alignment of stack pointer + * is assumed and required, e.g. by GCC4's -ftree-vectorize option. + */ + "andl $0xfffffff0, %esp\n\t" /* drop(?) stack ptr to 128-bit align */ +/* $esp should be aligned to a 16-byte boundary here (note we include an + * additional 4 bytes in a later push instruction). This will ensure $ebp + * in the function called below is aligned to a 0x8 boundary. SSE instructions + * like movapd/movdqa expect memory operand to be aligned on a 16-byte + * boundary. The GCC compiler will generate the memory operand using $ebp + * with an 8-byte offset. + */ + "subl $0xc, %esp\n\t" /* lower again; push/call below will re-align */ + "movl %esp, %ecx\n\t" /* ecx = d */ + "movl 8(%ebp), %edx\n\t" /* edx = this */ + "pushl %edx\n\t" /* push this. esp % 16 == 0 */ + + "movl 0x14(%ebp), %edx\n\t" + "call _invoke_copy_to_stack\n\t" + "movl 0x08(%ebp), %ecx\n\t" /* 'that' */ + "movl (%ecx), %edx\n\t" + "movl 0x0c(%ebp), %eax\n\t" /* function index */ + "leal (%edx,%eax,4), %edx\n\t" + "call *(%edx)\n\t" + "movl %ebp, %esp\n\t" + "popl %ebp\n\t" + "ret\n" + ".section .drectve\n\t" + ".ascii \" -export:NS_InvokeByIndex\"\n\t" + ".text\n\t" +); diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp new file mode 100644 index 0000000000..d669aafddf --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp @@ -0,0 +1,133 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +#ifndef WIN32 +#error "This code is for Win32 only" +#endif + +extern "C" { + +static +nsresult __stdcall +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, + uint32_t* args, uint32_t* stackBytesToPop) +{ + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info = nullptr; + uint8_t paramCount; + uint8_t i; + + // If anything fails before stackBytesToPop can be set then + // the failure is completely catastrophic! + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint32_t* ap = args; + for(i = 0; i < paramCount; i++, ap++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) + ap++; + + if(param.IsOut() || !type.IsArithmetic()) + { + dp->val.p = (void*) *ap; + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break; + case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break; + case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break; + case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break; + case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break; + case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break; + case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break; + case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break; + case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break; + case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break; + case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break; + case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break; + case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break; + default: + NS_ERROR("bad type"); + break; + } + } + *stackBytesToPop = ((uint32_t)ap) - ((uint32_t)args); + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +} // extern "C" + +static MOZ_NAKED void SharedStub(void) +{ + __asm { + push ebp // set up simple stack frame + mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args + push ecx // make room for a ptr + lea eax, [ebp-4] // pointer to stackBytesToPop + push eax + lea eax, [ebp+12] // pointer to args + push eax + push ecx // vtbl_index + mov eax, [ebp+8] // this + push eax + call PrepareAndDispatch + mov edx, [ebp+4] // return address + mov ecx, [ebp-4] // stackBytesToPop + add ecx, 8 // for 'this' and return address + mov esp, ebp + pop ebp + add esp, ecx // fix up stack pointer + jmp edx // simulate __stdcall return + } +} + +// these macros get expanded (many times) in the file #included below +#define STUB_ENTRY(n) \ +MOZ_NAKED nsresult __stdcall nsXPTCStubBase::Stub##n() \ +{ __asm mov ecx, n __asm jmp SharedStub } + +#define SENTINEL_ENTRY(n) \ +nsresult __stdcall nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4035) // OK to have no return value +#endif +#include "xptcstubsdef.inc" +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +void +xptc_dummy() +{ +} diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_aarch64.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs_aarch64.cpp new file mode 100644 index 0000000000..57d78c5a7a --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_aarch64.cpp @@ -0,0 +1,186 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +/* + * This is for AArch64 ABI + * + * When we're called, the "gp" registers are stored in gprData and + * the "fp" registers are stored in fprData. Each array has 8 regs + * but first reg in gprData is a placeholder for 'self'. + */ +extern "C" nsresult +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args, + uint64_t *gprData, double *fprData) +{ +#define PARAM_GPR_COUNT 8 +#define PARAM_FPR_COUNT 8 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + uint32_t paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint64_t* ap = args; + uint32_t next_gpr = 1; // skip first arg which is 'self' + uint32_t next_fpr = 0; + for (uint32_t i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (next_gpr < PARAM_GPR_COUNT) + next_gpr++; + else + ap++; + } + + if (param.IsOut() || !type.IsArithmetic()) { + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.p = (void*)gprData[next_gpr++]; + } else { + dp->val.p = (void*)*ap++; + } + continue; + } + + switch (type) { + case nsXPTType::T_I8: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.i8 = (int8_t)gprData[next_gpr++]; + } else { + dp->val.i8 = (int8_t)*ap++; + } + break; + + case nsXPTType::T_I16: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.i16 = (int16_t)gprData[next_gpr++]; + } else { + dp->val.i16 = (int16_t)*ap++; + } + break; + + case nsXPTType::T_I32: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.i32 = (int32_t)gprData[next_gpr++]; + } else { + dp->val.i32 = (int32_t)*ap++; + } + break; + + case nsXPTType::T_I64: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.i64 = (int64_t)gprData[next_gpr++]; + } else { + dp->val.i64 = (int64_t)*ap++; + } + break; + + case nsXPTType::T_U8: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.u8 = (uint8_t)gprData[next_gpr++]; + } else { + dp->val.u8 = (uint8_t)*ap++; + } + break; + + case nsXPTType::T_U16: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.u16 = (uint16_t)gprData[next_gpr++]; + } else { + dp->val.u16 = (uint16_t)*ap++; + } + break; + + case nsXPTType::T_U32: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.u32 = (uint32_t)gprData[next_gpr++]; + } else { + dp->val.u32 = (uint32_t)*ap++; + } + break; + + case nsXPTType::T_U64: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.u64 = (uint64_t)gprData[next_gpr++]; + } else { + dp->val.u64 = (uint64_t)*ap++; + } + break; + + case nsXPTType::T_FLOAT: + if (next_fpr < PARAM_FPR_COUNT) { + memcpy(&dp->val.f, &fprData[next_fpr++], sizeof(dp->val.f)); + } else { + memcpy(&dp->val.f, ap++, sizeof(dp->val.f)); + } + break; + + case nsXPTType::T_DOUBLE: + if (next_fpr < PARAM_FPR_COUNT) { + memcpy(&dp->val.d, &fprData[next_fpr++], sizeof(dp->val.d)); + } else { + memcpy(&dp->val.d, ap++, sizeof(dp->val.d)); + } + break; + + case nsXPTType::T_BOOL: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.b = (bool)(uint8_t)gprData[next_gpr++]; + } else { + dp->val.b = (bool)(uint8_t)*ap++; + } + break; + + case nsXPTType::T_CHAR: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.c = (char)gprData[next_gpr++]; + } else { + dp->val.c = (char)*ap++; + } + break; + + case nsXPTType::T_WCHAR: + if (next_gpr < PARAM_GPR_COUNT) { + dp->val.wc = (wchar_t)gprData[next_gpr++]; + } else { + dp->val.wc = (wchar_t)*ap++; + } + break; + + default: + NS_ASSERTION(0, "bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +#define STUB_ENTRY(n) /* defined in the assembly file */ + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_aarch64.asm b/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_aarch64.asm new file mode 100644 index 0000000000..28b3d8866f --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_aarch64.asm @@ -0,0 +1,306 @@ +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "ksarm64.h" + +NGPREGS EQU 8 +NFPREGS EQU 8 + + IMPORT |PrepareAndDispatch| + + TEXTAREA + + NESTED_ENTRY SharedStub + + PROLOG_SAVE_REG_PAIR x29, x30, #-16! + + sub sp, sp, #128 ; 8*(NGPREGS+NFPREGS) + stp x0, x1, [sp, #64+(0*8)] + stp x2, x3, [sp, #64+(2*8)] + stp x4, x5, [sp, #64+(4*8)] + stp x6, x7, [sp, #64+(6*8)] + stp d0, d1, [sp, #(0*8)] + stp d2, d3, [sp, #(2*8)] + stp d4, d5, [sp, #(4*8)] + stp d6, d7, [sp, #(6*8)] + + ; methodIndex passed from stub + mov w1, w17 + + add x2, sp, #144 ; 16+(8*(NGPREGS+NFPREGS)) + add x3, sp, #64 ; 8*NFPREGS + add x4, sp, #0 + + bl PrepareAndDispatch + + EPILOG_STACK_RESTORE + EPILOG_RESTORE_REG_PAIR x29, x30, #16! + EPILOG_RETURN + + NESTED_END SharedStub + + + MACRO + STUBENTRY $functionname, $paramcount + EXPORT |$functionname| + TEXTAREA + + LEAF_ENTRY |$functionname| + + mov w17, $paramcount + b SharedStub + + LEAF_END |$functionname| + + MEND + + STUBENTRY ?Stub3@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 3 + STUBENTRY ?Stub4@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 4 + STUBENTRY ?Stub5@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 5 + STUBENTRY ?Stub6@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 6 + STUBENTRY ?Stub7@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 7 + STUBENTRY ?Stub8@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 8 + STUBENTRY ?Stub9@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 9 + STUBENTRY ?Stub10@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 10 + STUBENTRY ?Stub11@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 11 + STUBENTRY ?Stub12@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 12 + STUBENTRY ?Stub13@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 13 + STUBENTRY ?Stub14@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 14 + STUBENTRY ?Stub15@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 15 + STUBENTRY ?Stub16@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 16 + STUBENTRY ?Stub17@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 17 + STUBENTRY ?Stub18@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 18 + STUBENTRY ?Stub19@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 19 + STUBENTRY ?Stub20@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 20 + STUBENTRY ?Stub21@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 21 + STUBENTRY ?Stub22@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 22 + STUBENTRY ?Stub23@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 23 + STUBENTRY ?Stub24@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 24 + STUBENTRY ?Stub25@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 25 + STUBENTRY ?Stub26@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 26 + STUBENTRY ?Stub27@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 27 + STUBENTRY ?Stub28@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 28 + STUBENTRY ?Stub29@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 29 + STUBENTRY ?Stub30@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 30 + STUBENTRY ?Stub31@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 31 + STUBENTRY ?Stub32@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 32 + STUBENTRY ?Stub33@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 33 + STUBENTRY ?Stub34@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 34 + STUBENTRY ?Stub35@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 35 + STUBENTRY ?Stub36@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 36 + STUBENTRY ?Stub37@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 37 + STUBENTRY ?Stub38@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 38 + STUBENTRY ?Stub39@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 39 + STUBENTRY ?Stub40@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 40 + STUBENTRY ?Stub41@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 41 + STUBENTRY ?Stub42@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 42 + STUBENTRY ?Stub43@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 43 + STUBENTRY ?Stub44@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 44 + STUBENTRY ?Stub45@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 45 + STUBENTRY ?Stub46@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 46 + STUBENTRY ?Stub47@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 47 + STUBENTRY ?Stub48@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 48 + STUBENTRY ?Stub49@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 49 + STUBENTRY ?Stub50@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 50 + STUBENTRY ?Stub51@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 51 + STUBENTRY ?Stub52@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 52 + STUBENTRY ?Stub53@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 53 + STUBENTRY ?Stub54@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 54 + STUBENTRY ?Stub55@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 55 + STUBENTRY ?Stub56@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 56 + STUBENTRY ?Stub57@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 57 + STUBENTRY ?Stub58@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 58 + STUBENTRY ?Stub59@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 59 + STUBENTRY ?Stub60@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 60 + STUBENTRY ?Stub61@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 61 + STUBENTRY ?Stub62@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 62 + STUBENTRY ?Stub63@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 63 + STUBENTRY ?Stub64@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 64 + STUBENTRY ?Stub65@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 65 + STUBENTRY ?Stub66@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 66 + STUBENTRY ?Stub67@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 67 + STUBENTRY ?Stub68@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 68 + STUBENTRY ?Stub69@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 69 + STUBENTRY ?Stub70@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 70 + STUBENTRY ?Stub71@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 71 + STUBENTRY ?Stub72@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 72 + STUBENTRY ?Stub73@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 73 + STUBENTRY ?Stub74@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 74 + STUBENTRY ?Stub75@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 75 + STUBENTRY ?Stub76@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 76 + STUBENTRY ?Stub77@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 77 + STUBENTRY ?Stub78@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 78 + STUBENTRY ?Stub79@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 79 + STUBENTRY ?Stub80@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 80 + STUBENTRY ?Stub81@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 81 + STUBENTRY ?Stub82@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 82 + STUBENTRY ?Stub83@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 83 + STUBENTRY ?Stub84@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 84 + STUBENTRY ?Stub85@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 85 + STUBENTRY ?Stub86@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 86 + STUBENTRY ?Stub87@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 87 + STUBENTRY ?Stub88@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 88 + STUBENTRY ?Stub89@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 89 + STUBENTRY ?Stub90@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 90 + STUBENTRY ?Stub91@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 91 + STUBENTRY ?Stub92@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 92 + STUBENTRY ?Stub93@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 93 + STUBENTRY ?Stub94@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 94 + STUBENTRY ?Stub95@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 95 + STUBENTRY ?Stub96@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 96 + STUBENTRY ?Stub97@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 97 + STUBENTRY ?Stub98@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 98 + STUBENTRY ?Stub99@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 99 + STUBENTRY ?Stub100@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 100 + STUBENTRY ?Stub101@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 101 + STUBENTRY ?Stub102@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 102 + STUBENTRY ?Stub103@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 103 + STUBENTRY ?Stub104@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 104 + STUBENTRY ?Stub105@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 105 + STUBENTRY ?Stub106@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 106 + STUBENTRY ?Stub107@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 107 + STUBENTRY ?Stub108@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 108 + STUBENTRY ?Stub109@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 109 + STUBENTRY ?Stub110@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 110 + STUBENTRY ?Stub111@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 111 + STUBENTRY ?Stub112@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 112 + STUBENTRY ?Stub113@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 113 + STUBENTRY ?Stub114@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 114 + STUBENTRY ?Stub115@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 115 + STUBENTRY ?Stub116@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 116 + STUBENTRY ?Stub117@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 117 + STUBENTRY ?Stub118@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 118 + STUBENTRY ?Stub119@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 119 + STUBENTRY ?Stub120@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 120 + STUBENTRY ?Stub121@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 121 + STUBENTRY ?Stub122@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 122 + STUBENTRY ?Stub123@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 123 + STUBENTRY ?Stub124@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 124 + STUBENTRY ?Stub125@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 125 + STUBENTRY ?Stub126@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 126 + STUBENTRY ?Stub127@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 127 + STUBENTRY ?Stub128@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 128 + STUBENTRY ?Stub129@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 129 + STUBENTRY ?Stub130@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 130 + STUBENTRY ?Stub131@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 131 + STUBENTRY ?Stub132@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 132 + STUBENTRY ?Stub133@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 133 + STUBENTRY ?Stub134@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 134 + STUBENTRY ?Stub135@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 135 + STUBENTRY ?Stub136@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 136 + STUBENTRY ?Stub137@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 137 + STUBENTRY ?Stub138@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 138 + STUBENTRY ?Stub139@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 139 + STUBENTRY ?Stub140@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 140 + STUBENTRY ?Stub141@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 141 + STUBENTRY ?Stub142@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 142 + STUBENTRY ?Stub143@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 143 + STUBENTRY ?Stub144@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 144 + STUBENTRY ?Stub145@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 145 + STUBENTRY ?Stub146@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 146 + STUBENTRY ?Stub147@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 147 + STUBENTRY ?Stub148@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 148 + STUBENTRY ?Stub149@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 149 + STUBENTRY ?Stub150@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 150 + STUBENTRY ?Stub151@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 151 + STUBENTRY ?Stub152@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 152 + STUBENTRY ?Stub153@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 153 + STUBENTRY ?Stub154@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 154 + STUBENTRY ?Stub155@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 155 + STUBENTRY ?Stub156@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 156 + STUBENTRY ?Stub157@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 157 + STUBENTRY ?Stub158@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 158 + STUBENTRY ?Stub159@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 159 + STUBENTRY ?Stub160@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 160 + STUBENTRY ?Stub161@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 161 + STUBENTRY ?Stub162@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 162 + STUBENTRY ?Stub163@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 163 + STUBENTRY ?Stub164@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 164 + STUBENTRY ?Stub165@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 165 + STUBENTRY ?Stub166@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 166 + STUBENTRY ?Stub167@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 167 + STUBENTRY ?Stub168@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 168 + STUBENTRY ?Stub169@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 169 + STUBENTRY ?Stub170@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 170 + STUBENTRY ?Stub171@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 171 + STUBENTRY ?Stub172@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 172 + STUBENTRY ?Stub173@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 173 + STUBENTRY ?Stub174@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 174 + STUBENTRY ?Stub175@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 175 + STUBENTRY ?Stub176@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 176 + STUBENTRY ?Stub177@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 177 + STUBENTRY ?Stub178@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 178 + STUBENTRY ?Stub179@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 179 + STUBENTRY ?Stub180@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 180 + STUBENTRY ?Stub181@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 181 + STUBENTRY ?Stub182@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 182 + STUBENTRY ?Stub183@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 183 + STUBENTRY ?Stub184@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 184 + STUBENTRY ?Stub185@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 185 + STUBENTRY ?Stub186@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 186 + STUBENTRY ?Stub187@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 187 + STUBENTRY ?Stub188@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 188 + STUBENTRY ?Stub189@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 189 + STUBENTRY ?Stub190@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 190 + STUBENTRY ?Stub191@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 191 + STUBENTRY ?Stub192@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 192 + STUBENTRY ?Stub193@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 193 + STUBENTRY ?Stub194@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 194 + STUBENTRY ?Stub195@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 195 + STUBENTRY ?Stub196@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 196 + STUBENTRY ?Stub197@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 197 + STUBENTRY ?Stub198@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 198 + STUBENTRY ?Stub199@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 199 + STUBENTRY ?Stub200@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 200 + STUBENTRY ?Stub201@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 201 + STUBENTRY ?Stub202@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 202 + STUBENTRY ?Stub203@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 203 + STUBENTRY ?Stub204@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 204 + STUBENTRY ?Stub205@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 205 + STUBENTRY ?Stub206@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 206 + STUBENTRY ?Stub207@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 207 + STUBENTRY ?Stub208@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 208 + STUBENTRY ?Stub209@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 209 + STUBENTRY ?Stub210@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 210 + STUBENTRY ?Stub211@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 211 + STUBENTRY ?Stub212@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 212 + STUBENTRY ?Stub213@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 213 + STUBENTRY ?Stub214@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 214 + STUBENTRY ?Stub215@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 215 + STUBENTRY ?Stub216@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 216 + STUBENTRY ?Stub217@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 217 + STUBENTRY ?Stub218@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 218 + STUBENTRY ?Stub219@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 219 + STUBENTRY ?Stub220@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 220 + STUBENTRY ?Stub221@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 221 + STUBENTRY ?Stub222@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 222 + STUBENTRY ?Stub223@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 223 + STUBENTRY ?Stub224@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 224 + STUBENTRY ?Stub225@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 225 + STUBENTRY ?Stub226@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 226 + STUBENTRY ?Stub227@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 227 + STUBENTRY ?Stub228@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 228 + STUBENTRY ?Stub229@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 229 + STUBENTRY ?Stub230@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 230 + STUBENTRY ?Stub231@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 231 + STUBENTRY ?Stub232@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 232 + STUBENTRY ?Stub233@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 233 + STUBENTRY ?Stub234@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 234 + STUBENTRY ?Stub235@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 235 + STUBENTRY ?Stub236@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 236 + STUBENTRY ?Stub237@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 237 + STUBENTRY ?Stub238@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 238 + STUBENTRY ?Stub239@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 239 + STUBENTRY ?Stub240@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 240 + STUBENTRY ?Stub241@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 241 + STUBENTRY ?Stub242@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 242 + STUBENTRY ?Stub243@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 243 + STUBENTRY ?Stub244@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 244 + STUBENTRY ?Stub245@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 245 + STUBENTRY ?Stub246@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 246 + STUBENTRY ?Stub247@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 247 + STUBENTRY ?Stub248@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 248 + STUBENTRY ?Stub249@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 249 + + END diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm b/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm new file mode 100644 index 0000000000..db2cc16bee --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm @@ -0,0 +1,335 @@ +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. + +extrn PrepareAndDispatch:PROC + +.code + +SharedStub PROC FRAME + sub rsp, 104 + .ALLOCSTACK 104 + .ENDPROLOG + + ; rcx is this pointer. Need backup for optimized build + + mov qword ptr [rsp+88], rcx + + ; + ; fist 4 parameters (1st is "this" pointer) are passed in registers. + ; + + ; for floating value + + movsd qword ptr [rsp+64], xmm1 + movsd qword ptr [rsp+72], xmm2 + movsd qword ptr [rsp+80], xmm3 + + ; for integer value + + mov qword ptr [rsp+40], rdx + mov qword ptr [rsp+48], r8 + mov qword ptr [rsp+56], r9 + + ; + ; Call PrepareAndDispatch function + ; + + ; 5th parameter (floating parameters) of PrepareAndDispatch + + lea r9, qword ptr [rsp+64] + mov qword ptr [rsp+32], r9 + + ; 4th parameter (normal parameters) of PrepareAndDispatch + + lea r9, qword ptr [rsp+40] + + ; 3rd parameter (pointer to args on stack) + + lea r8, qword ptr [rsp+40+104] + + ; 2nd parameter (vtbl_index) + + mov rdx, r11 + + ; 1st parameter (this) (rcx) + + call PrepareAndDispatch + + ; restore rcx + + mov rcx, qword ptr [rsp+88] + + ; + ; clean up register + ; + + add rsp, 104+8 + + ; set return address + + mov rdx, qword ptr [rsp-8] + + ; simulate __stdcall return + + jmp rdx + +SharedStub ENDP + + +STUBENTRY MACRO functionname, paramcount +functionname PROC + mov r11, paramcount + jmp SharedStub +functionname ENDP +ENDM + + STUBENTRY ?Stub3@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 3 + STUBENTRY ?Stub4@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 4 + STUBENTRY ?Stub5@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 5 + STUBENTRY ?Stub6@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 6 + STUBENTRY ?Stub7@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 7 + STUBENTRY ?Stub8@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 8 + STUBENTRY ?Stub9@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 9 + STUBENTRY ?Stub10@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 10 + STUBENTRY ?Stub11@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 11 + STUBENTRY ?Stub12@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 12 + STUBENTRY ?Stub13@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 13 + STUBENTRY ?Stub14@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 14 + STUBENTRY ?Stub15@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 15 + STUBENTRY ?Stub16@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 16 + STUBENTRY ?Stub17@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 17 + STUBENTRY ?Stub18@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 18 + STUBENTRY ?Stub19@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 19 + STUBENTRY ?Stub20@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 20 + STUBENTRY ?Stub21@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 21 + STUBENTRY ?Stub22@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 22 + STUBENTRY ?Stub23@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 23 + STUBENTRY ?Stub24@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 24 + STUBENTRY ?Stub25@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 25 + STUBENTRY ?Stub26@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 26 + STUBENTRY ?Stub27@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 27 + STUBENTRY ?Stub28@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 28 + STUBENTRY ?Stub29@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 29 + STUBENTRY ?Stub30@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 30 + STUBENTRY ?Stub31@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 31 + STUBENTRY ?Stub32@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 32 + STUBENTRY ?Stub33@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 33 + STUBENTRY ?Stub34@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 34 + STUBENTRY ?Stub35@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 35 + STUBENTRY ?Stub36@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 36 + STUBENTRY ?Stub37@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 37 + STUBENTRY ?Stub38@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 38 + STUBENTRY ?Stub39@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 39 + STUBENTRY ?Stub40@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 40 + STUBENTRY ?Stub41@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 41 + STUBENTRY ?Stub42@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 42 + STUBENTRY ?Stub43@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 43 + STUBENTRY ?Stub44@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 44 + STUBENTRY ?Stub45@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 45 + STUBENTRY ?Stub46@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 46 + STUBENTRY ?Stub47@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 47 + STUBENTRY ?Stub48@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 48 + STUBENTRY ?Stub49@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 49 + STUBENTRY ?Stub50@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 50 + STUBENTRY ?Stub51@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 51 + STUBENTRY ?Stub52@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 52 + STUBENTRY ?Stub53@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 53 + STUBENTRY ?Stub54@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 54 + STUBENTRY ?Stub55@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 55 + STUBENTRY ?Stub56@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 56 + STUBENTRY ?Stub57@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 57 + STUBENTRY ?Stub58@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 58 + STUBENTRY ?Stub59@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 59 + STUBENTRY ?Stub60@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 60 + STUBENTRY ?Stub61@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 61 + STUBENTRY ?Stub62@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 62 + STUBENTRY ?Stub63@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 63 + STUBENTRY ?Stub64@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 64 + STUBENTRY ?Stub65@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 65 + STUBENTRY ?Stub66@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 66 + STUBENTRY ?Stub67@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 67 + STUBENTRY ?Stub68@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 68 + STUBENTRY ?Stub69@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 69 + STUBENTRY ?Stub70@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 70 + STUBENTRY ?Stub71@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 71 + STUBENTRY ?Stub72@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 72 + STUBENTRY ?Stub73@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 73 + STUBENTRY ?Stub74@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 74 + STUBENTRY ?Stub75@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 75 + STUBENTRY ?Stub76@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 76 + STUBENTRY ?Stub77@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 77 + STUBENTRY ?Stub78@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 78 + STUBENTRY ?Stub79@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 79 + STUBENTRY ?Stub80@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 80 + STUBENTRY ?Stub81@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 81 + STUBENTRY ?Stub82@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 82 + STUBENTRY ?Stub83@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 83 + STUBENTRY ?Stub84@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 84 + STUBENTRY ?Stub85@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 85 + STUBENTRY ?Stub86@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 86 + STUBENTRY ?Stub87@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 87 + STUBENTRY ?Stub88@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 88 + STUBENTRY ?Stub89@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 89 + STUBENTRY ?Stub90@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 90 + STUBENTRY ?Stub91@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 91 + STUBENTRY ?Stub92@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 92 + STUBENTRY ?Stub93@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 93 + STUBENTRY ?Stub94@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 94 + STUBENTRY ?Stub95@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 95 + STUBENTRY ?Stub96@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 96 + STUBENTRY ?Stub97@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 97 + STUBENTRY ?Stub98@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 98 + STUBENTRY ?Stub99@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 99 + STUBENTRY ?Stub100@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 100 + STUBENTRY ?Stub101@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 101 + STUBENTRY ?Stub102@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 102 + STUBENTRY ?Stub103@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 103 + STUBENTRY ?Stub104@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 104 + STUBENTRY ?Stub105@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 105 + STUBENTRY ?Stub106@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 106 + STUBENTRY ?Stub107@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 107 + STUBENTRY ?Stub108@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 108 + STUBENTRY ?Stub109@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 109 + STUBENTRY ?Stub110@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 110 + STUBENTRY ?Stub111@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 111 + STUBENTRY ?Stub112@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 112 + STUBENTRY ?Stub113@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 113 + STUBENTRY ?Stub114@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 114 + STUBENTRY ?Stub115@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 115 + STUBENTRY ?Stub116@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 116 + STUBENTRY ?Stub117@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 117 + STUBENTRY ?Stub118@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 118 + STUBENTRY ?Stub119@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 119 + STUBENTRY ?Stub120@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 120 + STUBENTRY ?Stub121@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 121 + STUBENTRY ?Stub122@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 122 + STUBENTRY ?Stub123@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 123 + STUBENTRY ?Stub124@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 124 + STUBENTRY ?Stub125@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 125 + STUBENTRY ?Stub126@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 126 + STUBENTRY ?Stub127@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 127 + STUBENTRY ?Stub128@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 128 + STUBENTRY ?Stub129@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 129 + STUBENTRY ?Stub130@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 130 + STUBENTRY ?Stub131@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 131 + STUBENTRY ?Stub132@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 132 + STUBENTRY ?Stub133@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 133 + STUBENTRY ?Stub134@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 134 + STUBENTRY ?Stub135@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 135 + STUBENTRY ?Stub136@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 136 + STUBENTRY ?Stub137@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 137 + STUBENTRY ?Stub138@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 138 + STUBENTRY ?Stub139@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 139 + STUBENTRY ?Stub140@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 140 + STUBENTRY ?Stub141@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 141 + STUBENTRY ?Stub142@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 142 + STUBENTRY ?Stub143@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 143 + STUBENTRY ?Stub144@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 144 + STUBENTRY ?Stub145@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 145 + STUBENTRY ?Stub146@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 146 + STUBENTRY ?Stub147@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 147 + STUBENTRY ?Stub148@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 148 + STUBENTRY ?Stub149@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 149 + STUBENTRY ?Stub150@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 150 + STUBENTRY ?Stub151@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 151 + STUBENTRY ?Stub152@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 152 + STUBENTRY ?Stub153@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 153 + STUBENTRY ?Stub154@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 154 + STUBENTRY ?Stub155@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 155 + STUBENTRY ?Stub156@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 156 + STUBENTRY ?Stub157@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 157 + STUBENTRY ?Stub158@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 158 + STUBENTRY ?Stub159@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 159 + STUBENTRY ?Stub160@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 160 + STUBENTRY ?Stub161@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 161 + STUBENTRY ?Stub162@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 162 + STUBENTRY ?Stub163@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 163 + STUBENTRY ?Stub164@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 164 + STUBENTRY ?Stub165@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 165 + STUBENTRY ?Stub166@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 166 + STUBENTRY ?Stub167@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 167 + STUBENTRY ?Stub168@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 168 + STUBENTRY ?Stub169@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 169 + STUBENTRY ?Stub170@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 170 + STUBENTRY ?Stub171@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 171 + STUBENTRY ?Stub172@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 172 + STUBENTRY ?Stub173@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 173 + STUBENTRY ?Stub174@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 174 + STUBENTRY ?Stub175@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 175 + STUBENTRY ?Stub176@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 176 + STUBENTRY ?Stub177@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 177 + STUBENTRY ?Stub178@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 178 + STUBENTRY ?Stub179@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 179 + STUBENTRY ?Stub180@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 180 + STUBENTRY ?Stub181@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 181 + STUBENTRY ?Stub182@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 182 + STUBENTRY ?Stub183@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 183 + STUBENTRY ?Stub184@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 184 + STUBENTRY ?Stub185@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 185 + STUBENTRY ?Stub186@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 186 + STUBENTRY ?Stub187@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 187 + STUBENTRY ?Stub188@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 188 + STUBENTRY ?Stub189@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 189 + STUBENTRY ?Stub190@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 190 + STUBENTRY ?Stub191@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 191 + STUBENTRY ?Stub192@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 192 + STUBENTRY ?Stub193@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 193 + STUBENTRY ?Stub194@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 194 + STUBENTRY ?Stub195@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 195 + STUBENTRY ?Stub196@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 196 + STUBENTRY ?Stub197@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 197 + STUBENTRY ?Stub198@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 198 + STUBENTRY ?Stub199@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 199 + STUBENTRY ?Stub200@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 200 + STUBENTRY ?Stub201@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 201 + STUBENTRY ?Stub202@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 202 + STUBENTRY ?Stub203@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 203 + STUBENTRY ?Stub204@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 204 + STUBENTRY ?Stub205@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 205 + STUBENTRY ?Stub206@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 206 + STUBENTRY ?Stub207@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 207 + STUBENTRY ?Stub208@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 208 + STUBENTRY ?Stub209@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 209 + STUBENTRY ?Stub210@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 210 + STUBENTRY ?Stub211@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 211 + STUBENTRY ?Stub212@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 212 + STUBENTRY ?Stub213@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 213 + STUBENTRY ?Stub214@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 214 + STUBENTRY ?Stub215@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 215 + STUBENTRY ?Stub216@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 216 + STUBENTRY ?Stub217@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 217 + STUBENTRY ?Stub218@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 218 + STUBENTRY ?Stub219@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 219 + STUBENTRY ?Stub220@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 220 + STUBENTRY ?Stub221@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 221 + STUBENTRY ?Stub222@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 222 + STUBENTRY ?Stub223@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 223 + STUBENTRY ?Stub224@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 224 + STUBENTRY ?Stub225@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 225 + STUBENTRY ?Stub226@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 226 + STUBENTRY ?Stub227@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 227 + STUBENTRY ?Stub228@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 228 + STUBENTRY ?Stub229@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 229 + STUBENTRY ?Stub230@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 230 + STUBENTRY ?Stub231@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 231 + STUBENTRY ?Stub232@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 232 + STUBENTRY ?Stub233@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 233 + STUBENTRY ?Stub234@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 234 + STUBENTRY ?Stub235@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 235 + STUBENTRY ?Stub236@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 236 + STUBENTRY ?Stub237@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 237 + STUBENTRY ?Stub238@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 238 + STUBENTRY ?Stub239@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 239 + STUBENTRY ?Stub240@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 240 + STUBENTRY ?Stub241@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 241 + STUBENTRY ?Stub242@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 242 + STUBENTRY ?Stub243@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 243 + STUBENTRY ?Stub244@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 244 + STUBENTRY ?Stub245@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 245 + STUBENTRY ?Stub246@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 246 + STUBENTRY ?Stub247@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 247 + STUBENTRY ?Stub248@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 248 + STUBENTRY ?Stub249@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 249 + +END diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp new file mode 100644 index 0000000000..5f767a3988 --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp @@ -0,0 +1,188 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implement shared vtbl methods. */ + +#include "xptcprivate.h" + +/* + * This is for Windows XP 64-Bit Edition / Server 2003 for AMD64 or later. + */ + +extern "C" nsresult +PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args, + uint64_t *gprData, double *fprData) +{ +// +// "this" pointer is first parameter, so parameter count is 3. +// +#define PARAM_GPR_COUNT 3 +#define PARAM_FPR_COUNT 3 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info = nullptr; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self,"no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info,"no method info"); + + paramCount = info->GetParamCount(); + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint64_t* ap = args; + uint32_t iCount = 0; + + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (iCount < PARAM_GPR_COUNT) + iCount++; + else + ap++; + } + + if(param.IsOut() || !type.IsArithmetic()) + { + if (iCount < PARAM_GPR_COUNT) + dp->val.p = (void*)gprData[iCount++]; + else + dp->val.p = (void*)*ap++; + + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8: + if (iCount < PARAM_GPR_COUNT) + dp->val.i8 = (int8_t)gprData[iCount++]; + else + dp->val.i8 = *((int8_t*)ap++); + break; + + case nsXPTType::T_I16: + if (iCount < PARAM_GPR_COUNT) + dp->val.i16 = (int16_t)gprData[iCount++]; + else + dp->val.i16 = *((int16_t*)ap++); + break; + + case nsXPTType::T_I32: + if (iCount < PARAM_GPR_COUNT) + dp->val.i32 = (int32_t)gprData[iCount++]; + else + dp->val.i32 = *((int32_t*)ap++); + break; + + case nsXPTType::T_I64: + if (iCount < PARAM_GPR_COUNT) + dp->val.i64 = (int64_t)gprData[iCount++]; + else + dp->val.i64 = *((int64_t*)ap++); + break; + + case nsXPTType::T_U8: + if (iCount < PARAM_GPR_COUNT) + dp->val.u8 = (uint8_t)gprData[iCount++]; + else + dp->val.u8 = *((uint8_t*)ap++); + break; + + case nsXPTType::T_U16: + if (iCount < PARAM_GPR_COUNT) + dp->val.u16 = (uint16_t)gprData[iCount++]; + else + dp->val.u16 = *((uint16_t*)ap++); + break; + + case nsXPTType::T_U32: + if (iCount < PARAM_GPR_COUNT) + dp->val.u32 = (uint32_t)gprData[iCount++]; + else + dp->val.u32 = *((uint32_t*)ap++); + break; + + case nsXPTType::T_U64: + if (iCount < PARAM_GPR_COUNT) + dp->val.u64 = (uint64_t)gprData[iCount++]; + else + dp->val.u64 = *((uint64_t*)ap++); + break; + + case nsXPTType::T_FLOAT: + if (iCount < PARAM_FPR_COUNT) + // The value in xmm register is already prepared to + // be retrieved as a float. Therefore, we pass the + // value verbatim, as a double without conversion. + dp->val.d = (double)fprData[iCount++]; + else + dp->val.f = *((float*)ap++); + break; + + case nsXPTType::T_DOUBLE: + if (iCount < PARAM_FPR_COUNT) + dp->val.d = (double)fprData[iCount++]; + else + dp->val.d = *((double*)ap++); + break; + + case nsXPTType::T_BOOL: + if (iCount < PARAM_GPR_COUNT) + // We need the cast to uint8_t to remove garbage on upper 56-bit + // at first. + dp->val.b = (bool)(uint8_t)gprData[iCount++]; + else + dp->val.b = *((bool*)ap++); + break; + + case nsXPTType::T_CHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.c = (char)gprData[iCount++]; + else + dp->val.c = *((char*)ap++); + break; + + case nsXPTType::T_WCHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.wc = (wchar_t)gprData[iCount++]; + else + dp->val.wc = *((wchar_t*)ap++); + break; + + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +#define STUB_ENTRY(n) /* defined in the assembly file */ + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" + +void +xptc_dummy() +{ +} diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp new file mode 100644 index 0000000000..9c9d245c7f --- /dev/null +++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp @@ -0,0 +1,297 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "xptcprivate.h" + +/* + * This is for Windows 64 bit (x86_64) using GCC syntax + * Code was copied from the MSVC version. + */ + +#if !defined(_AMD64_) || !defined(__GNUC__) +# error xptcstubs_x86_64_gnu.cpp being used unexpectedly +#endif + +extern "C" nsresult __attribute__((__used__)) +PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex, + uint64_t * args, uint64_t * gprData, double *fprData) +{ +// +// "this" pointer is first parameter, so parameter count is 3. +// +#define PARAM_GPR_COUNT 3 +#define PARAM_FPR_COUNT 3 + + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info = nullptr; + uint8_t paramCount; + uint8_t i; + + NS_ASSERTION(self, "no self"); + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + NS_ASSERTION(info, "no method info"); + + paramCount = info->GetParamCount(); + + // + // setup variant array pointer + // + + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint64_t* ap = args; + uint32_t iCount = 0; + + for(i = 0; i < paramCount; i++) + { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (iCount < PARAM_GPR_COUNT) + iCount++; + else + ap++; + } + + if(param.IsOut() || !type.IsArithmetic()) + { + if (iCount < PARAM_GPR_COUNT) + dp->val.p = (void*)gprData[iCount++]; + else + dp->val.p = (void*)*ap++; + + continue; + } + // else + switch(type) + { + case nsXPTType::T_I8: + if (iCount < PARAM_GPR_COUNT) + dp->val.i8 = (int8_t)gprData[iCount++]; + else + dp->val.i8 = *((int8_t*)ap++); + break; + + case nsXPTType::T_I16: + if (iCount < PARAM_GPR_COUNT) + dp->val.i16 = (int16_t)gprData[iCount++]; + else + dp->val.i16 = *((int16_t*)ap++); + break; + + case nsXPTType::T_I32: + if (iCount < PARAM_GPR_COUNT) + dp->val.i32 = (int32_t)gprData[iCount++]; + else + dp->val.i32 = *((int32_t*)ap++); + break; + + case nsXPTType::T_I64: + if (iCount < PARAM_GPR_COUNT) + dp->val.i64 = (int64_t)gprData[iCount++]; + else + dp->val.i64 = *((int64_t*)ap++); + break; + + case nsXPTType::T_U8: + if (iCount < PARAM_GPR_COUNT) + dp->val.u8 = (uint8_t)gprData[iCount++]; + else + dp->val.u8 = *((uint8_t*)ap++); + break; + + case nsXPTType::T_U16: + if (iCount < PARAM_GPR_COUNT) + dp->val.u16 = (uint16_t)gprData[iCount++]; + else + dp->val.u16 = *((uint16_t*)ap++); + break; + + case nsXPTType::T_U32: + if (iCount < PARAM_GPR_COUNT) + dp->val.u32 = (uint32_t)gprData[iCount++]; + else + dp->val.u32 = *((uint32_t*)ap++); + break; + + case nsXPTType::T_U64: + if (iCount < PARAM_GPR_COUNT) + dp->val.u64 = (uint64_t)gprData[iCount++]; + else + dp->val.u64 = *((uint64_t*)ap++); + break; + + case nsXPTType::T_FLOAT: + if (iCount < PARAM_FPR_COUNT) + // The value in xmm register is already prepared to + // be retrieved as a float. Therefore, we pass the + // value verbatim, as a double without conversion. + dp->val.d = (double)fprData[iCount++]; + else + dp->val.f = *((float*)ap++); + break; + + case nsXPTType::T_DOUBLE: + if (iCount < PARAM_FPR_COUNT) + dp->val.d = (double)fprData[iCount++]; + else + dp->val.d = *((double*)ap++); + break; + + case nsXPTType::T_BOOL: + if (iCount < PARAM_GPR_COUNT) + // We need the cast to uint8_t to remove garbage on upper 56-bit + // at first. + dp->val.b = (bool)(uint8_t)gprData[iCount++]; + else + dp->val.b = *((bool*)ap++); + break; + + case nsXPTType::T_CHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.c = (char)gprData[iCount++]; + else + dp->val.c = *((char*)ap++); + break; + + case nsXPTType::T_WCHAR: + if (iCount < PARAM_GPR_COUNT) + dp->val.wc = (wchar_t)gprData[iCount++]; + else + dp->val.wc = *((wchar_t*)ap++); + break; + + default: + NS_ASSERTION(0, "bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + + return result; +} + +__asm__ ( + ".text\n" + ".intel_syntax noprefix\n" /* switch to Intel syntax to look like the MSVC assembly */ + ".globl SharedStub\n" + ".def SharedStub ; .scl 3 ; .type 46 ; .endef \n" + "SharedStub:\n" + "sub rsp, 104\n" + + /* rcx is this pointer. Need backup for optimized build */ + + "mov qword ptr [rsp+88], rcx\n" + + /* + * fist 4 parameters (1st is "this" pointer) are passed in registers. + */ + + /* for floating value */ + + "movsd qword ptr [rsp+64], xmm1\n" + "movsd qword ptr [rsp+72], xmm2\n" + "movsd qword ptr [rsp+80], xmm3\n" + + /* for integer value */ + + "mov qword ptr [rsp+40], rdx\n" + "mov qword ptr [rsp+48], r8\n" + "mov qword ptr [rsp+56], r9\n" + + /* + * Call PrepareAndDispatch function + */ + + /* 5th parameter (floating parameters) of PrepareAndDispatch */ + + "lea r9, qword ptr [rsp+64]\n" + "mov qword ptr [rsp+32], r9\n" + + /* 4th parameter (normal parameters) of PrepareAndDispatch */ + + "lea r9, qword ptr [rsp+40]\n" + + /* 3rd parameter (pointer to args on stack) */ + + "lea r8, qword ptr [rsp+40+104]\n" + + /* 2nd parameter (vtbl_index) */ + + "mov rdx, r11\n" + + /* 1st parameter (this) (rcx) */ + + "call PrepareAndDispatch\n" + + /* restore rcx */ + + "mov rcx, qword ptr [rsp+88]\n" + + /* + * clean up register + */ + + "add rsp, 104+8\n" + + /* set return address */ + + "mov rdx, qword ptr [rsp-8]\n" + + /* simulate __stdcall return */ + + "jmp rdx\n" + + /* back to AT&T syntax */ + ".att_syntax\n" +); + +#define STUB_ENTRY(n) \ +asm(".intel_syntax noprefix\n" /* this is in intel syntax */ \ + ".text\n" \ + ".align 2\n" \ + ".if " #n " < 10\n" \ + ".globl _ZN14nsXPTCStubBase5Stub" #n "Ev\n" \ + ".def _ZN14nsXPTCStubBase5Stub" #n "Ev\n" \ + ".scl 2\n" /* external */ \ + ".type 46\n" /* function returning unsigned int */ \ + ".endef\n" \ + "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n" \ + ".elseif " #n " < 100\n" \ + ".globl _ZN14nsXPTCStubBase6Stub" #n "Ev\n" \ + ".def _ZN14nsXPTCStubBase6Stub" #n "Ev\n" \ + ".scl 2\n" /* external */\ + ".type 46\n" /* function returning unsigned int */ \ + ".endef\n" \ + "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n" \ + ".elseif " #n " < 1000\n" \ + ".globl _ZN14nsXPTCStubBase7Stub" #n "Ev\n" \ + ".def _ZN14nsXPTCStubBase7Stub" #n "Ev\n" \ + ".scl 2\n" /* external */ \ + ".type 46\n" /* function returning unsigned int */ \ + ".endef\n" \ + "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n" \ + ".else\n" \ + ".err \"stub number " #n " >= 1000 not yet supported\"\n" \ + ".endif\n" \ + "mov r11, " #n "\n" \ + "jmp SharedStub\n" \ + ".att_syntax\n" /* back to AT&T syntax */ \ + ""); + +#define SENTINEL_ENTRY(n) \ +nsresult nsXPTCStubBase::Sentinel##n() \ +{ \ + NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ +} + +#include "xptcstubsdef.inc" diff --git a/xpcom/reflect/xptcall/moz.build b/xpcom/reflect/xptcall/moz.build new file mode 100644 index 0000000000..16923a3357 --- /dev/null +++ b/xpcom/reflect/xptcall/moz.build @@ -0,0 +1,20 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DIRS += ["md"] + +SOURCES += [ + "xptcall.cpp", +] + +EXPORTS += [ + "nsXPTCUtils.h", + "xptcall.h", + "xptcstubsdecl.inc", + "xptcstubsdef.inc", +] + +FINAL_LIBRARY = "xul" diff --git a/xpcom/reflect/xptcall/nsXPTCUtils.h b/xpcom/reflect/xptcall/nsXPTCUtils.h new file mode 100644 index 0000000000..4f5060360d --- /dev/null +++ b/xpcom/reflect/xptcall/nsXPTCUtils.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsXPTCUtils_h__ +#define nsXPTCUtils_h__ + +#include "xptcall.h" +#include "mozilla/MemoryReporting.h" + +/** + * A helper class that initializes an xptcall helper at construction + * and releases it at destruction. + */ +class nsAutoXPTCStub : protected nsIXPTCProxy { + public: + nsISomeInterface* mXPTCStub; + + protected: + nsAutoXPTCStub() : mXPTCStub(nullptr) {} + + nsresult InitStub(const nsIID& aIID) { + return NS_GetXPTCallStub(aIID, this, &mXPTCStub); + } + + ~nsAutoXPTCStub() { + if (mXPTCStub) { + NS_DestroyXPTCallStub(mXPTCStub); + } + } + + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { + return mXPTCStub + ? NS_SizeOfIncludingThisXPTCallStub(mXPTCStub, aMallocSizeOf) + : 0; + } +}; + +#endif // nsXPTCUtils_h__ diff --git a/xpcom/reflect/xptcall/porting.html b/xpcom/reflect/xptcall/porting.html new file mode 100644 index 0000000000..a149aa144a --- /dev/null +++ b/xpcom/reflect/xptcall/porting.html @@ -0,0 +1,237 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<html> + <head> + <title>xptcall Porting Guide</title> + </head> + <body bgcolor="white"> + <h2><center>xptcall Porting Guide</center></h2> + + <h3>Overview</h3> + + <blockquote> + <a href="http://www.mozilla.org/scriptable/xptcall-faq.html"> xptcall</a> + is a library that supports both invoking methods on arbitrary xpcom + objects and implementing classes whose objects can impersonate any xpcom + interface. It does this using platform specific assembly language code. + This code needs to be ported to all platforms that want to support xptcall + (and thus mozilla). + </blockquote> + + <h3>The tree</h3> + + <blockquote> + <pre> +<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall">mozilla/xpcom/reflect/xptcall</a> + +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public">public</a> // exported headers + +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src">src</a> // core source + | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md">md</a> // platform specific parts + | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/mac">mac</a> // mac ppc + | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix">unix</a> // all unix + | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32">win32</a> // win32 + | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/test">test</a> // simple tests to get started + \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests">tests</a> // full tests via api +</pre> + + Porters are free to create subdirectories under the base <code>md</code> + directory for their given platforms and to integrate into the build system + as appropriate for their platform. + </blockquote> + + <h3>Theory of operation</h3> + + <blockquote> + There are really two pieces of functionality: <i>invoke</i> and + <i>stubs</i>... + + <p> + The <b><i>invoke</i></b> functionality requires the implementation of + the following on each platform (from + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcall.h" + >xptcall/xptcall.h</a + >): + </p> + + <pre> +XPTC_PUBLIC_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, nsXPTCVariant* params); +</pre + > + + Calling code is expected to supply an array of + <code>nsXPTCVariant</code> structs. These are discriminated unions + describing the type and value of each parameter of the target function. + The platform specific code then builds a call frame and invokes the method + indicated by the index <code>methodIndex</code> on the xpcom interface + <code>that</code>. + + <p> + Here are examples of this implementation for + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp" + >Win32</a + > + and + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix/xptcinvoke_unixish_x86.cpp" + >Linux x86, NetBSD x86, and FreeBSD</a + >. Both of these implementations use the basic strategy of: figure out + how much stack space is needed for the params, make the space in a new + frame, copy the params to that space, invoke the method, cleanup and + return. C++ is used where appropriate, Assembly language is used where + necessary. Inline assembly language is used here, but it is equally + valid to use separate assembly language source files. Porters can decide + how best to do this for their platforms. + </p> + + <p> + The <b><i>stubs</i></b> functionality is more complex. The goal here is + a class whose vtbl can look like the vtbl of any arbitrary xpcom + interface. Objects of this class can then be built to impersonate any + xpcom object. The base interface for this is (from + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcall.h" + >xptcall/xptcall.h</a + >): + </p> + + <pre> +class nsXPTCStubBase : public nsISupports +{ +public: + // Include generated vtbl stub declarations. + // These are virtual and *also* implemented by this class.. +#include "xptcstubsdecl.inc" + + // The following methods must be provided by inheritor of this class. + + // return a refcounted pointer to the InterfaceInfo for this object + // NOTE: on some platforms this MUST not fail or we crash! + NS_IMETHOD GetInterfaceInfo(const nsXPTInterfaceInfo** info) = 0; + + // call this method and return result + NS_IMETHOD CallMethod(uint16_t methodIndex, + const nsXPTMethodInfo* info, + nsXPTCMiniVariant* params) = 0; +}; +</pre + > + + Code that wishes to make use of this <i>stubs</i> functionality (such as + <a href="http://www.mozilla.org/scriptable/">XPConnect</a>) implement a + class which inherits from <code>nsXPTCStubBase</code> and implements the + <code>GetInterfaceInfo</code> and <code>CallMethod</code> to let the + platform specific code know how to get interface information and how to + dispatch methods once their parameters have been pulled out of the + platform specific calling frame. + + <p> + Porters of this functionality implement the platform specific code for + the + <i>stub</i> methods that fill the vtbl for this class. The idea here is + that the class has a vtbl full of a large number of generic stubs. All + instances of this class share that vtbl and the same stubs. The stubs + forward calls to a platform specific method that uses the interface + information supplied by the overridden <code>GetInterfaceInfo</code> to + extract the parameters and build an array of platform independent + <code>nsXPTCMiniVariant</code> structs which are in turn passed on to + the overridden <code>CallMethod</code>. The platform dependent code is + responsible for doing any cleanup and returning. + </p> + + <p> + The stub methods are declared in + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcstubsdecl.inc" + >xptcall/xptcstubsdecl.inc</a + >. These are '#included' into the declaration of + <code>nsXPTCStubBase</code>. A similar include file (<a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/xptcstubsdef.inc" + >xptcall/xptcstubsdef.inc</a + >) is expanded using platform specific macros to define the stub + functions. These '.inc' files are checked into cvs. However, they can be + regenerated as necessary (i.e. to change the number of stubs or to + change their specific declaration) using the Perl script + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/genstubs.pl" + >xptcall/genstubs.pl</a + >. + </p> + + <p> + Here are examples of this implementation for + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp" + >Win32</a + > + and + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/unix/xptcstubs_unixish_x86.cpp" + >Linux x86, NetBSD x86, and FreeBSD</a + >. Both of these examples use inline assembly language. That is just how + I decided to do it. You can do it as you choose. + </p> + + <p> + The Win32 version is somewhat tighter because the __declspec(naked) + feature allows for very small stubs. However, the __stdcall requires the + callee to clean up the stack, so it is imperative that the interface + information scheme allow the code to determine the correct stack pointer + fixup for return without fail, else the process will crash. + </p> + + <p> + I opted to use inline assembler for the gcc Linux x86 port. I ended up + with larger stubs than I would have preferred rather than battle the + compiler over what would happen to the stack before my asm code began + running. + </p> + + <p> + I believe that the non-assembly parts of these files can be copied and + reused with minimal (but not zero) platform specific tweaks. Feel free + to copy and paste as necessary. Please remember that safety and + reliability are more important than speed optimizations. This code is + primarily used to connect XPCOM components with JavaScript; function + call overhead is a <b>tiny</b> part of the time involved. + </p> + + <p> + I put together + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/md/test" + >xptcall/md/test + </a> + as a place to evolve the basic functionality as a port is coming + together. Not all of the functionality is exercised, but it is a place + to get started. + <a + href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests" + >xptcall/tests + </a> + has an api level test for <code>NS_InvokeByIndex</code>, but no tests + for the <i>stubs</i> functionality. Such a test ought to be written, but + this has not yet been done. + </p> + + <p> + A full 'test' at this point requires building the client and running the + XPConnect test called <i>TestXPC</i> in + <a href="http://lxr.mozilla.org/mozilla/source/js/xpconnect/tests" + >mozilla/js/xpconnect/tests </a + >. + </p> + </blockquote> + + <hr /> + <b>Author:</b> + <a href="mailto:jband@netscape.com" + >John Bandhauer <jband@netscape.com></a + ><br /> + <b>Last modified:</b> 31 May 1999 + </body> +</html> diff --git a/xpcom/reflect/xptcall/xptcall.cpp b/xpcom/reflect/xptcall/xptcall.cpp new file mode 100644 index 0000000000..0b28791b54 --- /dev/null +++ b/xpcom/reflect/xptcall/xptcall.cpp @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* entry point wrappers. */ + +#include "xptcprivate.h" + +using namespace mozilla; + +NS_IMETHODIMP +nsXPTCStubBase::QueryInterface(REFNSIID aIID, void** aInstancePtr) { + if (aIID.Equals(mEntry->IID())) { + NS_ADDREF_THIS(); + *aInstancePtr = static_cast<nsISupports*>(this); + return NS_OK; + } + + return mOuter->QueryInterface(aIID, aInstancePtr); +} + +NS_IMETHODIMP_(MozExternalRefCountType) +nsXPTCStubBase::AddRef() { return mOuter->AddRef(); } + +NS_IMETHODIMP_(MozExternalRefCountType) +nsXPTCStubBase::Release() { return mOuter->Release(); } + +EXPORT_XPCOM_API(nsresult) +NS_GetXPTCallStub(REFNSIID aIID, nsIXPTCProxy* aOuter, + nsISomeInterface** aResult) { + if (NS_WARN_IF(!aOuter) || NS_WARN_IF(!aResult)) return NS_ERROR_INVALID_ARG; + + const nsXPTInterfaceInfo* iie = nsXPTInterfaceInfo::ByIID(aIID); + if (!iie || iie->IsBuiltinClass()) { + return NS_ERROR_FAILURE; + } + + *aResult = new nsXPTCStubBase(aOuter, iie); + return NS_OK; +} + +EXPORT_XPCOM_API(void) +NS_DestroyXPTCallStub(nsISomeInterface* aStub) { + nsXPTCStubBase* stub = static_cast<nsXPTCStubBase*>(aStub); + delete (stub); +} + +EXPORT_XPCOM_API(size_t) +NS_SizeOfIncludingThisXPTCallStub(const nsISomeInterface* aStub, + mozilla::MallocSizeOf aMallocSizeOf) { + // We could cast aStub to nsXPTCStubBase, but that class doesn't seem to own + // anything, so just measure the size of the object itself. + return aMallocSizeOf(aStub); +} diff --git a/xpcom/reflect/xptcall/xptcall.h b/xpcom/reflect/xptcall/xptcall.h new file mode 100644 index 0000000000..a36ca53d23 --- /dev/null +++ b/xpcom/reflect/xptcall/xptcall.h @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Public declarations for xptcall. */ + +#ifndef xptcall_h___ +#define xptcall_h___ + +#include "nscore.h" +#include "nsISupports.h" +#include "xptinfo.h" +#include "js/Value.h" +#include "mozilla/MemoryReporting.h" + +struct nsXPTCMiniVariant { + // No ctors or dtors so that we can use arrays of these on the stack + // with no penalty. + union Union { + int8_t i8; + int16_t i16; + int32_t i32; + int64_t i64; + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint64_t u64; + float f; + double d; + bool b; + char c; + char16_t wc; + void* p; + }; + + Union val; +}; + +static_assert(offsetof(nsXPTCMiniVariant, val) == 0, + "nsXPTCMiniVariant must be a thin wrapper"); + +struct nsXPTCVariant { + union ExtendedVal { + // ExtendedVal is an extension on nsXPTCMiniVariant. It contains types + // unknown to the assembly implementations which must be passed by indirect + // semantics. + // + // nsXPTCVariant contains enough space to store ExtendedVal inline, which + // can be used to store these types when IsIndirect() is true. + nsXPTCMiniVariant mini; + + nsID nsid; + nsCString nscstr; + nsString nsstr; + JS::Value jsval; + xpt::detail::UntypedTArray array; + + // This type contains non-standard-layout types, so needs an explicit + // Ctor/Dtor - we'll just delete them. + ExtendedVal() = delete; + ~ExtendedVal() = delete; + }; + + union { + // The `val` field from nsXPTCMiniVariant. + nsXPTCMiniVariant::Union val; + + // Storage for any extended variants. + ExtendedVal ext; + }; + + nsXPTType type; + uint8_t flags; + + // Clear to a valid, null state. + nsXPTCVariant() { + memset(this, 0, sizeof(nsXPTCVariant)); + type = nsXPTType::T_VOID; + } + + enum { + // + // Bitflag definitions + // + + // Indicates that we &val.p should be passed n the stack, i.e. that + // val should be passed by reference. + IS_INDIRECT = 0x1, + }; + + void ClearFlags() { flags = 0; } + void SetIndirect() { flags |= IS_INDIRECT; } + + bool IsIndirect() const { return 0 != (flags & IS_INDIRECT); } + + // Implicitly convert to nsXPTCMiniVariant. + operator nsXPTCMiniVariant&() { return *(nsXPTCMiniVariant*)&val; } + operator const nsXPTCMiniVariant&() const { + return *(const nsXPTCMiniVariant*)&val; + } + + // As this type contains an anonymous union, we need to provide an explicit + // destructor. + ~nsXPTCVariant() {} +}; + +static_assert(offsetof(nsXPTCVariant, val) == offsetof(nsXPTCVariant, ext), + "nsXPTCVariant::{ext,val} must have matching offsets"); + +// static_assert that nsXPTCVariant::ExtendedVal is large enough and +// well-aligned enough for every XPT-supported type. +#define XPT_CHECK_SIZEOF(xpt, type) \ + static_assert(sizeof(nsXPTCVariant::ExtendedVal) >= sizeof(type), \ + "nsXPTCVariant::ext not big enough for " #xpt " (" #type ")"); \ + static_assert(MOZ_ALIGNOF(nsXPTCVariant::ExtendedVal) >= MOZ_ALIGNOF(type), \ + "nsXPTCVariant::ext not aligned enough for " #xpt " (" #type \ + ")"); +XPT_FOR_EACH_TYPE(XPT_CHECK_SIZEOF) +#undef XPT_CHECK_SIZEOF + +class nsIXPTCProxy : public nsISupports { + public: + NS_IMETHOD CallMethod(uint16_t aMethodIndex, const nsXPTMethodInfo* aInfo, + nsXPTCMiniVariant* aParams) = 0; +}; + +/** + * This is a typedef to avoid confusion between the canonical + * nsISupports* that provides object identity and an interface pointer + * for inheriting interfaces that aren't known at compile-time. + */ +typedef nsISupports nsISomeInterface; + +/** + * Get a proxy object to implement the specified interface. + * + * @param aIID The IID of the interface to implement. + * @param aOuter An object to receive method calls from the proxy object. + * The stub forwards QueryInterface/AddRef/Release to the + * outer object. The proxy object does not hold a reference to + * the outer object; it is the caller's responsibility to + * ensure that this pointer remains valid until the stub has + * been destroyed. + * @param aStub Out parameter for the new proxy object. The object is + * not addrefed. The object never destroys itself. It must be + * explicitly destroyed by calling + * NS_DestroyXPTCallStub when it is no longer needed. + */ +XPCOM_API(nsresult) +NS_GetXPTCallStub(REFNSIID aIID, nsIXPTCProxy* aOuter, + nsISomeInterface** aStub); + +/** + * Destroys an XPTCall stub previously created with NS_GetXPTCallStub. + */ +XPCOM_API(void) +NS_DestroyXPTCallStub(nsISomeInterface* aStub); + +/** + * Measures the size of an XPTCall stub previously created with + * NS_GetXPTCallStub. + */ +XPCOM_API(size_t) +NS_SizeOfIncludingThisXPTCallStub(const nsISomeInterface* aStub, + mozilla::MallocSizeOf aMallocSizeOf); + +// this is extern "C" because on some platforms it is implemented in assembly +extern "C" nsresult NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, + nsXPTCVariant* params); + +#endif /* xptcall_h___ */ diff --git a/xpcom/reflect/xptcall/xptcprivate.h b/xpcom/reflect/xptcall/xptcprivate.h new file mode 100644 index 0000000000..02f408dc38 --- /dev/null +++ b/xpcom/reflect/xptcall/xptcprivate.h @@ -0,0 +1,68 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* All the xptcall private declarations - only include locally. */ + +#ifndef xptcprivate_h___ +#define xptcprivate_h___ + +#include "xptcall.h" +#include "mozilla/Attributes.h" + +#if !defined(__ia64) || \ + (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__)) +# define STUB_ENTRY(n) NS_IMETHOD Stub##n() = 0; +#else +# define STUB_ENTRY(n) \ + NS_IMETHOD Stub##n(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, \ + uint64_t, uint64_t, uint64_t) = 0; +#endif + +#define SENTINEL_ENTRY(n) NS_IMETHOD Sentinel##n() = 0; + +class nsIXPTCStubBase : public nsISupports { + public: +#include "xptcstubsdef.inc" +}; + +#undef STUB_ENTRY +#undef SENTINEL_ENTRY + +#if !defined(__ia64) || \ + (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__)) +# define STUB_ENTRY(n) NS_IMETHOD Stub##n() override; +#else +# define STUB_ENTRY(n) \ + NS_IMETHOD Stub##n(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, \ + uint64_t, uint64_t, uint64_t) override; +#endif + +#define SENTINEL_ENTRY(n) NS_IMETHOD Sentinel##n() override; + +class nsXPTCStubBase final : public nsIXPTCStubBase { + public: + NS_DECL_ISUPPORTS_INHERITED + +#include "xptcstubsdef.inc" + + nsXPTCStubBase(nsIXPTCProxy* aOuter, const nsXPTInterfaceInfo* aEntry) + : mOuter(aOuter), mEntry(aEntry) {} + + nsIXPTCProxy* mOuter; + const nsXPTInterfaceInfo* mEntry; + + ~nsXPTCStubBase() = default; +}; + +#undef STUB_ENTRY +#undef SENTINEL_ENTRY + +#if defined(__clang__) || defined(__GNUC__) +# define ATTRIBUTE_USED __attribute__((__used__)) +#else +# define ATTRIBUTE_USED +#endif + +#endif /* xptcprivate_h___ */ diff --git a/xpcom/reflect/xptcall/xptcstubsdecl.inc b/xpcom/reflect/xptcall/xptcstubsdecl.inc new file mode 100644 index 0000000000..91d35fe322 --- /dev/null +++ b/xpcom/reflect/xptcall/xptcstubsdecl.inc @@ -0,0 +1,761 @@ +/* generated file - DO NOT EDIT */ + +/* includes 247 stub entries, and 5 sentinel entries */ + +/* +* declarations of normal stubs... +* 0 is QueryInterface +* 1 is AddRef +* 2 is Release +*/ +#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__)) +NS_IMETHOD Stub3(); +NS_IMETHOD Stub4(); +NS_IMETHOD Stub5(); +NS_IMETHOD Stub6(); +NS_IMETHOD Stub7(); +NS_IMETHOD Stub8(); +NS_IMETHOD Stub9(); +NS_IMETHOD Stub10(); +NS_IMETHOD Stub11(); +NS_IMETHOD Stub12(); +NS_IMETHOD Stub13(); +NS_IMETHOD Stub14(); +NS_IMETHOD Stub15(); +NS_IMETHOD Stub16(); +NS_IMETHOD Stub17(); +NS_IMETHOD Stub18(); +NS_IMETHOD Stub19(); +NS_IMETHOD Stub20(); +NS_IMETHOD Stub21(); +NS_IMETHOD Stub22(); +NS_IMETHOD Stub23(); +NS_IMETHOD Stub24(); +NS_IMETHOD Stub25(); +NS_IMETHOD Stub26(); +NS_IMETHOD Stub27(); +NS_IMETHOD Stub28(); +NS_IMETHOD Stub29(); +NS_IMETHOD Stub30(); +NS_IMETHOD Stub31(); +NS_IMETHOD Stub32(); +NS_IMETHOD Stub33(); +NS_IMETHOD Stub34(); +NS_IMETHOD Stub35(); +NS_IMETHOD Stub36(); +NS_IMETHOD Stub37(); +NS_IMETHOD Stub38(); +NS_IMETHOD Stub39(); +NS_IMETHOD Stub40(); +NS_IMETHOD Stub41(); +NS_IMETHOD Stub42(); +NS_IMETHOD Stub43(); +NS_IMETHOD Stub44(); +NS_IMETHOD Stub45(); +NS_IMETHOD Stub46(); +NS_IMETHOD Stub47(); +NS_IMETHOD Stub48(); +NS_IMETHOD Stub49(); +NS_IMETHOD Stub50(); +NS_IMETHOD Stub51(); +NS_IMETHOD Stub52(); +NS_IMETHOD Stub53(); +NS_IMETHOD Stub54(); +NS_IMETHOD Stub55(); +NS_IMETHOD Stub56(); +NS_IMETHOD Stub57(); +NS_IMETHOD Stub58(); +NS_IMETHOD Stub59(); +NS_IMETHOD Stub60(); +NS_IMETHOD Stub61(); +NS_IMETHOD Stub62(); +NS_IMETHOD Stub63(); +NS_IMETHOD Stub64(); +NS_IMETHOD Stub65(); +NS_IMETHOD Stub66(); +NS_IMETHOD Stub67(); +NS_IMETHOD Stub68(); +NS_IMETHOD Stub69(); +NS_IMETHOD Stub70(); +NS_IMETHOD Stub71(); +NS_IMETHOD Stub72(); +NS_IMETHOD Stub73(); +NS_IMETHOD Stub74(); +NS_IMETHOD Stub75(); +NS_IMETHOD Stub76(); +NS_IMETHOD Stub77(); +NS_IMETHOD Stub78(); +NS_IMETHOD Stub79(); +NS_IMETHOD Stub80(); +NS_IMETHOD Stub81(); +NS_IMETHOD Stub82(); +NS_IMETHOD Stub83(); +NS_IMETHOD Stub84(); +NS_IMETHOD Stub85(); +NS_IMETHOD Stub86(); +NS_IMETHOD Stub87(); +NS_IMETHOD Stub88(); +NS_IMETHOD Stub89(); +NS_IMETHOD Stub90(); +NS_IMETHOD Stub91(); +NS_IMETHOD Stub92(); +NS_IMETHOD Stub93(); +NS_IMETHOD Stub94(); +NS_IMETHOD Stub95(); +NS_IMETHOD Stub96(); +NS_IMETHOD Stub97(); +NS_IMETHOD Stub98(); +NS_IMETHOD Stub99(); +NS_IMETHOD Stub100(); +NS_IMETHOD Stub101(); +NS_IMETHOD Stub102(); +NS_IMETHOD Stub103(); +NS_IMETHOD Stub104(); +NS_IMETHOD Stub105(); +NS_IMETHOD Stub106(); +NS_IMETHOD Stub107(); +NS_IMETHOD Stub108(); +NS_IMETHOD Stub109(); +NS_IMETHOD Stub110(); +NS_IMETHOD Stub111(); +NS_IMETHOD Stub112(); +NS_IMETHOD Stub113(); +NS_IMETHOD Stub114(); +NS_IMETHOD Stub115(); +NS_IMETHOD Stub116(); +NS_IMETHOD Stub117(); +NS_IMETHOD Stub118(); +NS_IMETHOD Stub119(); +NS_IMETHOD Stub120(); +NS_IMETHOD Stub121(); +NS_IMETHOD Stub122(); +NS_IMETHOD Stub123(); +NS_IMETHOD Stub124(); +NS_IMETHOD Stub125(); +NS_IMETHOD Stub126(); +NS_IMETHOD Stub127(); +NS_IMETHOD Stub128(); +NS_IMETHOD Stub129(); +NS_IMETHOD Stub130(); +NS_IMETHOD Stub131(); +NS_IMETHOD Stub132(); +NS_IMETHOD Stub133(); +NS_IMETHOD Stub134(); +NS_IMETHOD Stub135(); +NS_IMETHOD Stub136(); +NS_IMETHOD Stub137(); +NS_IMETHOD Stub138(); +NS_IMETHOD Stub139(); +NS_IMETHOD Stub140(); +NS_IMETHOD Stub141(); +NS_IMETHOD Stub142(); +NS_IMETHOD Stub143(); +NS_IMETHOD Stub144(); +NS_IMETHOD Stub145(); +NS_IMETHOD Stub146(); +NS_IMETHOD Stub147(); +NS_IMETHOD Stub148(); +NS_IMETHOD Stub149(); +NS_IMETHOD Stub150(); +NS_IMETHOD Stub151(); +NS_IMETHOD Stub152(); +NS_IMETHOD Stub153(); +NS_IMETHOD Stub154(); +NS_IMETHOD Stub155(); +NS_IMETHOD Stub156(); +NS_IMETHOD Stub157(); +NS_IMETHOD Stub158(); +NS_IMETHOD Stub159(); +NS_IMETHOD Stub160(); +NS_IMETHOD Stub161(); +NS_IMETHOD Stub162(); +NS_IMETHOD Stub163(); +NS_IMETHOD Stub164(); +NS_IMETHOD Stub165(); +NS_IMETHOD Stub166(); +NS_IMETHOD Stub167(); +NS_IMETHOD Stub168(); +NS_IMETHOD Stub169(); +NS_IMETHOD Stub170(); +NS_IMETHOD Stub171(); +NS_IMETHOD Stub172(); +NS_IMETHOD Stub173(); +NS_IMETHOD Stub174(); +NS_IMETHOD Stub175(); +NS_IMETHOD Stub176(); +NS_IMETHOD Stub177(); +NS_IMETHOD Stub178(); +NS_IMETHOD Stub179(); +NS_IMETHOD Stub180(); +NS_IMETHOD Stub181(); +NS_IMETHOD Stub182(); +NS_IMETHOD Stub183(); +NS_IMETHOD Stub184(); +NS_IMETHOD Stub185(); +NS_IMETHOD Stub186(); +NS_IMETHOD Stub187(); +NS_IMETHOD Stub188(); +NS_IMETHOD Stub189(); +NS_IMETHOD Stub190(); +NS_IMETHOD Stub191(); +NS_IMETHOD Stub192(); +NS_IMETHOD Stub193(); +NS_IMETHOD Stub194(); +NS_IMETHOD Stub195(); +NS_IMETHOD Stub196(); +NS_IMETHOD Stub197(); +NS_IMETHOD Stub198(); +NS_IMETHOD Stub199(); +NS_IMETHOD Stub200(); +NS_IMETHOD Stub201(); +NS_IMETHOD Stub202(); +NS_IMETHOD Stub203(); +NS_IMETHOD Stub204(); +NS_IMETHOD Stub205(); +NS_IMETHOD Stub206(); +NS_IMETHOD Stub207(); +NS_IMETHOD Stub208(); +NS_IMETHOD Stub209(); +NS_IMETHOD Stub210(); +NS_IMETHOD Stub211(); +NS_IMETHOD Stub212(); +NS_IMETHOD Stub213(); +NS_IMETHOD Stub214(); +NS_IMETHOD Stub215(); +NS_IMETHOD Stub216(); +NS_IMETHOD Stub217(); +NS_IMETHOD Stub218(); +NS_IMETHOD Stub219(); +NS_IMETHOD Stub220(); +NS_IMETHOD Stub221(); +NS_IMETHOD Stub222(); +NS_IMETHOD Stub223(); +NS_IMETHOD Stub224(); +NS_IMETHOD Stub225(); +NS_IMETHOD Stub226(); +NS_IMETHOD Stub227(); +NS_IMETHOD Stub228(); +NS_IMETHOD Stub229(); +NS_IMETHOD Stub230(); +NS_IMETHOD Stub231(); +NS_IMETHOD Stub232(); +NS_IMETHOD Stub233(); +NS_IMETHOD Stub234(); +NS_IMETHOD Stub235(); +NS_IMETHOD Stub236(); +NS_IMETHOD Stub237(); +NS_IMETHOD Stub238(); +NS_IMETHOD Stub239(); +NS_IMETHOD Stub240(); +NS_IMETHOD Stub241(); +NS_IMETHOD Stub242(); +NS_IMETHOD Stub243(); +NS_IMETHOD Stub244(); +NS_IMETHOD Stub245(); +NS_IMETHOD Stub246(); +NS_IMETHOD Stub247(); +NS_IMETHOD Stub248(); +NS_IMETHOD Stub249(); +#else +NS_IMETHOD Stub3(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub4(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub5(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub6(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub7(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub8(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub9(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub10(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub11(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub12(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub13(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub14(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub15(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub16(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub17(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub18(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub19(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub20(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub21(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub22(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub23(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub24(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub25(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub26(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub27(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub28(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub29(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub30(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub31(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub32(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub33(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub34(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub35(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub36(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub37(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub38(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub39(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub40(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub41(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub42(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub43(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub44(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub45(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub46(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub47(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub48(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub49(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub50(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub51(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub52(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub53(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub54(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub55(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub56(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub57(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub58(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub59(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub60(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub61(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub62(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub63(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub64(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub65(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub66(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub67(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub68(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub69(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub70(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub71(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub72(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub73(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub74(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub75(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub76(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub77(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub78(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub79(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub80(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub81(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub82(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub83(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub84(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub85(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub86(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub87(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub88(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub89(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub90(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub91(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub92(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub93(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub94(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub95(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub96(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub97(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub98(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub99(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub100(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub101(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub102(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub103(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub104(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub105(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub106(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub107(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub108(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub109(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub110(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub111(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub112(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub113(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub114(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub115(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub116(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub117(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub118(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub119(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub120(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub121(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub122(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub123(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub124(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub125(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub126(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub127(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub128(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub129(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub130(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub131(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub132(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub133(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub134(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub135(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub136(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub137(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub138(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub139(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub140(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub141(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub142(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub143(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub144(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub145(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub146(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub147(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub148(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub149(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub150(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub151(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub152(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub153(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub154(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub155(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub156(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub157(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub158(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub159(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub160(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub161(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub162(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub163(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub164(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub165(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub166(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub167(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub168(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub169(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub170(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub171(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub172(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub173(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub174(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub175(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub176(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub177(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub178(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub179(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub180(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub181(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub182(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub183(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub184(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub185(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub186(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub187(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub188(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub189(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub190(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub191(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub192(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub193(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub194(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub195(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub196(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub197(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub198(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub199(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub200(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub201(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub202(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub203(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub204(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub205(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub206(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub207(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub208(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub209(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub210(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub211(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub212(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub213(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub214(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub215(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub216(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub217(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub218(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub219(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub220(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub221(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub222(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub223(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub224(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub225(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub226(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub227(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub228(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub229(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub230(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub231(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub232(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub233(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub234(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub235(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub236(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub237(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub238(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub239(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub240(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub241(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub242(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub243(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub244(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub245(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub246(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub247(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub248(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +NS_IMETHOD Stub249(uint64_t,uint64_t, + uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t); +#endif + +/* declarations of sentinel stubs */ +NS_IMETHOD Sentinel0(); +NS_IMETHOD Sentinel1(); +NS_IMETHOD Sentinel2(); +NS_IMETHOD Sentinel3(); +NS_IMETHOD Sentinel4(); diff --git a/xpcom/reflect/xptcall/xptcstubsdef.inc b/xpcom/reflect/xptcall/xptcstubsdef.inc new file mode 100644 index 0000000000..2df455406a --- /dev/null +++ b/xpcom/reflect/xptcall/xptcstubsdef.inc @@ -0,0 +1,252 @@ +STUB_ENTRY(3) +STUB_ENTRY(4) +STUB_ENTRY(5) +STUB_ENTRY(6) +STUB_ENTRY(7) +STUB_ENTRY(8) +STUB_ENTRY(9) +STUB_ENTRY(10) +STUB_ENTRY(11) +STUB_ENTRY(12) +STUB_ENTRY(13) +STUB_ENTRY(14) +STUB_ENTRY(15) +STUB_ENTRY(16) +STUB_ENTRY(17) +STUB_ENTRY(18) +STUB_ENTRY(19) +STUB_ENTRY(20) +STUB_ENTRY(21) +STUB_ENTRY(22) +STUB_ENTRY(23) +STUB_ENTRY(24) +STUB_ENTRY(25) +STUB_ENTRY(26) +STUB_ENTRY(27) +STUB_ENTRY(28) +STUB_ENTRY(29) +STUB_ENTRY(30) +STUB_ENTRY(31) +STUB_ENTRY(32) +STUB_ENTRY(33) +STUB_ENTRY(34) +STUB_ENTRY(35) +STUB_ENTRY(36) +STUB_ENTRY(37) +STUB_ENTRY(38) +STUB_ENTRY(39) +STUB_ENTRY(40) +STUB_ENTRY(41) +STUB_ENTRY(42) +STUB_ENTRY(43) +STUB_ENTRY(44) +STUB_ENTRY(45) +STUB_ENTRY(46) +STUB_ENTRY(47) +STUB_ENTRY(48) +STUB_ENTRY(49) +STUB_ENTRY(50) +STUB_ENTRY(51) +STUB_ENTRY(52) +STUB_ENTRY(53) +STUB_ENTRY(54) +STUB_ENTRY(55) +STUB_ENTRY(56) +STUB_ENTRY(57) +STUB_ENTRY(58) +STUB_ENTRY(59) +STUB_ENTRY(60) +STUB_ENTRY(61) +STUB_ENTRY(62) +STUB_ENTRY(63) +STUB_ENTRY(64) +STUB_ENTRY(65) +STUB_ENTRY(66) +STUB_ENTRY(67) +STUB_ENTRY(68) +STUB_ENTRY(69) +STUB_ENTRY(70) +STUB_ENTRY(71) +STUB_ENTRY(72) +STUB_ENTRY(73) +STUB_ENTRY(74) +STUB_ENTRY(75) +STUB_ENTRY(76) +STUB_ENTRY(77) +STUB_ENTRY(78) +STUB_ENTRY(79) +STUB_ENTRY(80) +STUB_ENTRY(81) +STUB_ENTRY(82) +STUB_ENTRY(83) +STUB_ENTRY(84) +STUB_ENTRY(85) +STUB_ENTRY(86) +STUB_ENTRY(87) +STUB_ENTRY(88) +STUB_ENTRY(89) +STUB_ENTRY(90) +STUB_ENTRY(91) +STUB_ENTRY(92) +STUB_ENTRY(93) +STUB_ENTRY(94) +STUB_ENTRY(95) +STUB_ENTRY(96) +STUB_ENTRY(97) +STUB_ENTRY(98) +STUB_ENTRY(99) +STUB_ENTRY(100) +STUB_ENTRY(101) +STUB_ENTRY(102) +STUB_ENTRY(103) +STUB_ENTRY(104) +STUB_ENTRY(105) +STUB_ENTRY(106) +STUB_ENTRY(107) +STUB_ENTRY(108) +STUB_ENTRY(109) +STUB_ENTRY(110) +STUB_ENTRY(111) +STUB_ENTRY(112) +STUB_ENTRY(113) +STUB_ENTRY(114) +STUB_ENTRY(115) +STUB_ENTRY(116) +STUB_ENTRY(117) +STUB_ENTRY(118) +STUB_ENTRY(119) +STUB_ENTRY(120) +STUB_ENTRY(121) +STUB_ENTRY(122) +STUB_ENTRY(123) +STUB_ENTRY(124) +STUB_ENTRY(125) +STUB_ENTRY(126) +STUB_ENTRY(127) +STUB_ENTRY(128) +STUB_ENTRY(129) +STUB_ENTRY(130) +STUB_ENTRY(131) +STUB_ENTRY(132) +STUB_ENTRY(133) +STUB_ENTRY(134) +STUB_ENTRY(135) +STUB_ENTRY(136) +STUB_ENTRY(137) +STUB_ENTRY(138) +STUB_ENTRY(139) +STUB_ENTRY(140) +STUB_ENTRY(141) +STUB_ENTRY(142) +STUB_ENTRY(143) +STUB_ENTRY(144) +STUB_ENTRY(145) +STUB_ENTRY(146) +STUB_ENTRY(147) +STUB_ENTRY(148) +STUB_ENTRY(149) +STUB_ENTRY(150) +STUB_ENTRY(151) +STUB_ENTRY(152) +STUB_ENTRY(153) +STUB_ENTRY(154) +STUB_ENTRY(155) +STUB_ENTRY(156) +STUB_ENTRY(157) +STUB_ENTRY(158) +STUB_ENTRY(159) +STUB_ENTRY(160) +STUB_ENTRY(161) +STUB_ENTRY(162) +STUB_ENTRY(163) +STUB_ENTRY(164) +STUB_ENTRY(165) +STUB_ENTRY(166) +STUB_ENTRY(167) +STUB_ENTRY(168) +STUB_ENTRY(169) +STUB_ENTRY(170) +STUB_ENTRY(171) +STUB_ENTRY(172) +STUB_ENTRY(173) +STUB_ENTRY(174) +STUB_ENTRY(175) +STUB_ENTRY(176) +STUB_ENTRY(177) +STUB_ENTRY(178) +STUB_ENTRY(179) +STUB_ENTRY(180) +STUB_ENTRY(181) +STUB_ENTRY(182) +STUB_ENTRY(183) +STUB_ENTRY(184) +STUB_ENTRY(185) +STUB_ENTRY(186) +STUB_ENTRY(187) +STUB_ENTRY(188) +STUB_ENTRY(189) +STUB_ENTRY(190) +STUB_ENTRY(191) +STUB_ENTRY(192) +STUB_ENTRY(193) +STUB_ENTRY(194) +STUB_ENTRY(195) +STUB_ENTRY(196) +STUB_ENTRY(197) +STUB_ENTRY(198) +STUB_ENTRY(199) +STUB_ENTRY(200) +STUB_ENTRY(201) +STUB_ENTRY(202) +STUB_ENTRY(203) +STUB_ENTRY(204) +STUB_ENTRY(205) +STUB_ENTRY(206) +STUB_ENTRY(207) +STUB_ENTRY(208) +STUB_ENTRY(209) +STUB_ENTRY(210) +STUB_ENTRY(211) +STUB_ENTRY(212) +STUB_ENTRY(213) +STUB_ENTRY(214) +STUB_ENTRY(215) +STUB_ENTRY(216) +STUB_ENTRY(217) +STUB_ENTRY(218) +STUB_ENTRY(219) +STUB_ENTRY(220) +STUB_ENTRY(221) +STUB_ENTRY(222) +STUB_ENTRY(223) +STUB_ENTRY(224) +STUB_ENTRY(225) +STUB_ENTRY(226) +STUB_ENTRY(227) +STUB_ENTRY(228) +STUB_ENTRY(229) +STUB_ENTRY(230) +STUB_ENTRY(231) +STUB_ENTRY(232) +STUB_ENTRY(233) +STUB_ENTRY(234) +STUB_ENTRY(235) +STUB_ENTRY(236) +STUB_ENTRY(237) +STUB_ENTRY(238) +STUB_ENTRY(239) +STUB_ENTRY(240) +STUB_ENTRY(241) +STUB_ENTRY(242) +STUB_ENTRY(243) +STUB_ENTRY(244) +STUB_ENTRY(245) +STUB_ENTRY(246) +STUB_ENTRY(247) +STUB_ENTRY(248) +STUB_ENTRY(249) +SENTINEL_ENTRY(0) +SENTINEL_ENTRY(1) +SENTINEL_ENTRY(2) +SENTINEL_ENTRY(3) +SENTINEL_ENTRY(4) diff --git a/xpcom/reflect/xptinfo/moz.build b/xpcom/reflect/xptinfo/moz.build new file mode 100644 index 0000000000..9e4ce23258 --- /dev/null +++ b/xpcom/reflect/xptinfo/moz.build @@ -0,0 +1,21 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +UNIFIED_SOURCES += [ + "xptinfo.cpp", +] + +SOURCES += [ + "!xptdata.cpp", +] + +EXPORTS += [ + "xptinfo.h", +] + +include("/ipc/chromium/chromium-config.mozbuild") + +FINAL_LIBRARY = "xul" diff --git a/xpcom/reflect/xptinfo/xptcodegen.py b/xpcom/reflect/xptinfo/xptcodegen.py new file mode 100644 index 0000000000..d2859703b8 --- /dev/null +++ b/xpcom/reflect/xptinfo/xptcodegen.py @@ -0,0 +1,646 @@ +#!/usr/bin/env python +# jsonlink.py - Merge JSON typelib files into a .cpp file +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import json +from collections import OrderedDict + +import buildconfig +from perfecthash import PerfectHash + +# Pick a nice power-of-two size for our intermediate PHF tables. +PHFSIZE = 512 + + +def indented(s): + return s.replace("\n", "\n ") + + +def cpp(v): + if type(v) == bool: + return "true" if v else "false" + return str(v) + + +def mkstruct(*fields): + def mk(comment, **vals): + assert len(fields) == len(vals) + r = "{ // " + comment + r += indented(",".join("\n/* %s */ %s" % (k, cpp(vals[k])) for k in fields)) + r += "\n}" + return r + + return mk + + +########################################################## +# Ensure these fields are in the same order as xptinfo.h # +########################################################## +nsXPTInterfaceInfo = mkstruct( + "mIID", + "mName", + "mParent", + "mBuiltinClass", + "mMainProcessScriptableOnly", + "mMethods", + "mConsts", + "mFunction", + "mNumMethods", + "mNumConsts", +) + +########################################################## +# Ensure these fields are in the same order as xptinfo.h # +########################################################## +nsXPTType = mkstruct( + "mTag", + "mInParam", + "mOutParam", + "mOptionalParam", + "mData1", + "mData2", +) + +########################################################## +# Ensure these fields are in the same order as xptinfo.h # +########################################################## +nsXPTParamInfo = mkstruct( + "mType", +) + +########################################################## +# Ensure these fields are in the same order as xptinfo.h # +########################################################## +nsXPTMethodInfo = mkstruct( + "mName", + "mParams", + "mNumParams", + "mGetter", + "mSetter", + "mReflectable", + "mOptArgc", + "mContext", + "mHasRetval", + "mIsSymbol", +) + +########################################################## +# Ensure these fields are in the same order as xptinfo.h # +########################################################## +nsXPTDOMObjectInfo = mkstruct( + "mUnwrap", + "mWrap", + "mCleanup", +) + +########################################################## +# Ensure these fields are in the same order as xptinfo.h # +########################################################## +nsXPTConstantInfo = mkstruct( + "mName", + "mSigned", + "mValue", +) + + +# Helper functions for dealing with IIDs. +# +# Unfortunately, the way we represent IIDs in memory depends on the endianness +# of the target architecture. We store an nsIID as a 16-byte, 4-tuple of: +# +# (uint32_t, uint16_t, uint16_t, [uint8_t; 8]) +# +# Unfortunately, this means that when we hash the bytes of the nsIID on a +# little-endian target system, we need to hash them in little-endian order. +# These functions let us split the input hexadecimal string into components, +# encoding each as a little-endian value, and producing an accurate bytearray. +# +# It would be nice to have a consistent representation of IIDs in memory such +# that we don't have to do these gymnastics to get an accurate hash. + + +def split_at_idxs(s, lengths): + idx = 0 + for length in lengths: + yield s[idx : idx + length] + idx += length + assert idx == len(s) + + +def split_iid(iid): # Get the individual components out of an IID string. + iid = iid.replace("-", "") # Strip any '-' delimiters + return tuple(split_at_idxs(iid, (8, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2))) + + +def iid_bytes(iid): # Get the byte representation of the IID for hashing. + bs = bytearray() + for num in split_iid(iid): + b = bytearray.fromhex(num) + # Match endianness of the target platform for each component + if buildconfig.substs["TARGET_ENDIANNESS"] == "little": + b.reverse() + bs += b + return bs + + +# Split a 16-bit integer into its high and low 8 bits +def splitint(i): + assert i < 2**16 + return (i >> 8, i & 0xFF) + + +# Occasionally in xpconnect, we need to fabricate types to pass into the +# conversion methods. In some cases, these types need to be arrays, which hold +# indicies into the extra types array. +# +# These are some types which should have known indexes into the extra types +# array. +utility_types = [ + {"tag": "TD_INT8"}, + {"tag": "TD_UINT8"}, + {"tag": "TD_INT16"}, + {"tag": "TD_UINT16"}, + {"tag": "TD_INT32"}, + {"tag": "TD_UINT32"}, + {"tag": "TD_INT64"}, + {"tag": "TD_UINT64"}, + {"tag": "TD_FLOAT"}, + {"tag": "TD_DOUBLE"}, + {"tag": "TD_BOOL"}, + {"tag": "TD_CHAR"}, + {"tag": "TD_WCHAR"}, + {"tag": "TD_NSIDPTR"}, + {"tag": "TD_PSTRING"}, + {"tag": "TD_PWSTRING"}, + {"tag": "TD_INTERFACE_IS_TYPE", "iid_is": 0}, +] + + +# Core of the code generator. Takes a list of raw JSON XPT interfaces, and +# writes out a file containing the necessary static declarations into fd. +def link_to_cpp(interfaces, fd, header_fd): + # Perfect Hash from IID to interface. + iid_phf = PerfectHash(interfaces, PHFSIZE, key=lambda i: iid_bytes(i["uuid"])) + for idx, iface in enumerate(iid_phf.entries): + iface["idx"] = idx # Store the index in iid_phf of the entry. + + # Perfect Hash from name to iid_phf index. + name_phf = PerfectHash(interfaces, PHFSIZE, key=lambda i: i["name"].encode("ascii")) + + def interface_idx(name): + entry = name and name_phf.get_entry(name.encode("ascii")) + if entry: + return entry["idx"] + 1 # 1-based, use 0 as a sentinel. + return 0 + + # NOTE: State used while linking. This is done with closures rather than a + # class due to how this file's code evolved. + includes = set() + types = [] + type_cache = {} + params = [] + param_cache = {} + methods = [] + max_params = 0 + method_with_max_params = None + consts = [] + domobjects = [] + domobject_cache = {} + strings = OrderedDict() + + def lower_uuid(uuid): + return ( + "{0x%s, 0x%s, 0x%s, {0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s}}" + % split_iid(uuid) + ) + + def lower_domobject(do): + assert do["tag"] == "TD_DOMOBJECT" + + idx = domobject_cache.get(do["name"]) + if idx is None: + idx = domobject_cache[do["name"]] = len(domobjects) + + includes.add(do["headerFile"]) + domobjects.append( + nsXPTDOMObjectInfo( + "%d = %s" % (idx, do["name"]), + # These methods are defined at the top of the generated file. + mUnwrap="UnwrapDOMObject<mozilla::dom::prototypes::id::%s, %s>" + % (do["name"], do["native"]), + mWrap="WrapDOMObject<%s>" % do["native"], + mCleanup="CleanupDOMObject<%s>" % do["native"], + ) + ) + + return idx + + def lower_string(s): + if s in strings: + # We've already seen this string. + return strings[s] + elif len(strings): + # Get the last string we inserted (should be O(1) on OrderedDict). + last_s = next(reversed(strings)) + strings[s] = strings[last_s] + len(last_s) + 1 + else: + strings[s] = 0 + return strings[s] + + def lower_symbol(s): + return "uint32_t(JS::SymbolCode::%s)" % s + + def lower_extra_type(type): + key = describe_type(type) + idx = type_cache.get(key) + if idx is None: + idx = type_cache[key] = len(types) + # Make sure `types` is the proper length for any recursive calls + # to `lower_extra_type` that might happen from within `lower_type`. + types.append(None) + realtype = lower_type(type) + types[idx] = realtype + return idx + + def describe_type(type): # Create the type's documentation comment. + tag = type["tag"][3:].lower() + if tag == "legacy_array": + return "%s[size_is=%d]" % (describe_type(type["element"]), type["size_is"]) + elif tag == "array": + return "Array<%s>" % describe_type(type["element"]) + elif tag == "interface_type" or tag == "domobject": + return type["name"] + elif tag == "interface_is_type": + return "iid_is(%d)" % type["iid_is"] + elif tag.endswith("_size_is"): + return "%s(size_is=%d)" % (tag, type["size_is"]) + return tag + + def lower_type(type, in_=False, out=False, optional=False): + tag = type["tag"] + d1 = d2 = 0 + + # TD_VOID is used for types that can't be represented in JS, so they + # should not be represented in the XPT info. + assert tag != "TD_VOID" + + if tag == "TD_LEGACY_ARRAY": + d1 = type["size_is"] + d2 = lower_extra_type(type["element"]) + + elif tag == "TD_ARRAY": + # NOTE: TD_ARRAY can hold 16 bits of type index, while + # TD_LEGACY_ARRAY can only hold 8. + d1, d2 = splitint(lower_extra_type(type["element"])) + + elif tag == "TD_INTERFACE_TYPE": + d1, d2 = splitint(interface_idx(type["name"])) + + elif tag == "TD_INTERFACE_IS_TYPE": + d1 = type["iid_is"] + + elif tag == "TD_DOMOBJECT": + d1, d2 = splitint(lower_domobject(type)) + + elif tag.endswith("_SIZE_IS"): + d1 = type["size_is"] + + assert d1 < 256 and d2 < 256, "Data values too large" + return nsXPTType( + describe_type(type), + mTag=tag, + mData1=d1, + mData2=d2, + mInParam=in_, + mOutParam=out, + mOptionalParam=optional, + ) + + def lower_param(param, paramname): + params.append( + nsXPTParamInfo( + "%d = %s" % (len(params), paramname), + mType=lower_type( + param["type"], + in_="in" in param["flags"], + out="out" in param["flags"], + optional="optional" in param["flags"], + ), + ) + ) + + def is_type_reflectable(type): + # All native types end up getting tagged as void*, or as wrapper types around void* + if type["tag"] == "TD_VOID": + return False + if type["tag"] in ("TD_ARRAY", "TD_LEGACY_ARRAY"): + return is_type_reflectable(type["element"]) + return True + + def is_method_reflectable(method): + if "hidden" in method["flags"]: + return False + + for param in method["params"]: + # Reflected methods can't use non-reflectable types. + if not is_type_reflectable(param["type"]): + return False + + return True + + def lower_method(method, ifacename): + methodname = "%s::%s" % (ifacename, method["name"]) + + isSymbol = "symbol" in method["flags"] + reflectable = is_method_reflectable(method) + + if not reflectable: + # Hide the parameters of methods that can't be called from JS to + # reduce the size of the file. + paramidx = name = numparams = 0 + else: + if isSymbol: + name = lower_symbol(method["name"]) + else: + name = lower_string(method["name"]) + + numparams = len(method["params"]) + + # Check cache for parameters + cachekey = json.dumps(method["params"], sort_keys=True) + paramidx = param_cache.get(cachekey) + if paramidx is None: + paramidx = param_cache[cachekey] = len(params) + for idx, param in enumerate(method["params"]): + lower_param(param, "%s[%d]" % (methodname, idx)) + + nonlocal max_params, method_with_max_params + if numparams > max_params: + max_params = numparams + method_with_max_params = methodname + methods.append( + nsXPTMethodInfo( + "%d = %s" % (len(methods), methodname), + mName=name, + mParams=paramidx, + mNumParams=numparams, + # Flags + mGetter="getter" in method["flags"], + mSetter="setter" in method["flags"], + mReflectable=reflectable, + mOptArgc="optargc" in method["flags"], + mContext="jscontext" in method["flags"], + mHasRetval="hasretval" in method["flags"], + mIsSymbol=isSymbol, + ) + ) + + def lower_const(const, ifacename): + assert const["type"]["tag"] in [ + "TD_INT16", + "TD_INT32", + "TD_UINT8", + "TD_UINT16", + "TD_UINT32", + ] + is_signed = const["type"]["tag"] in ["TD_INT16", "TD_INT32"] + + # Constants are always either signed or unsigned 16 or 32 bit integers, + # which we will only need to convert to JS values. To save on space, + # don't bother storing the type, and instead just store a 32-bit + # unsigned integer, and stash whether to interpret it as signed. + consts.append( + nsXPTConstantInfo( + "%d = %s::%s" % (len(consts), ifacename, const["name"]), + mName=lower_string(const["name"]), + mSigned=is_signed, + mValue="(uint32_t)%d" % const["value"], + ) + ) + + def ancestors(iface): + yield iface + while iface["parent"]: + iface = name_phf.get_entry(iface["parent"].encode("ascii")) + yield iface + + def lower_iface(iface): + method_cnt = sum(len(i["methods"]) for i in ancestors(iface)) + const_cnt = sum(len(i["consts"]) for i in ancestors(iface)) + + # The number of maximum methods is not arbitrary. It is the same value + # as in xpcom/reflect/xptcall/genstubs.pl; do not change this value + # without changing that one or you WILL see problems. + # + # In addition, mNumMethods and mNumConsts are stored as a 8-bit ints, + # meaning we cannot exceed 255 methods/consts on any interface. + assert method_cnt < 250, "%s has too many methods" % iface["name"] + assert const_cnt < 256, "%s has too many constants" % iface["name"] + + # Store the lowered interface as 'cxx' on the iface object. + iface["cxx"] = nsXPTInterfaceInfo( + "%d = %s" % (iface["idx"], iface["name"]), + mIID=lower_uuid(iface["uuid"]), + mName=lower_string(iface["name"]), + mParent=interface_idx(iface["parent"]), + mMethods=len(methods), + mNumMethods=method_cnt, + mConsts=len(consts), + mNumConsts=const_cnt, + # Flags + mBuiltinClass="builtinclass" in iface["flags"], + mMainProcessScriptableOnly="main_process_only" in iface["flags"], + mFunction="function" in iface["flags"], + ) + + # Lower methods and constants used by this interface + for method in iface["methods"]: + lower_method(method, iface["name"]) + for const in iface["consts"]: + lower_const(const, iface["name"]) + + # Lower the types which have fixed indexes first, and check that the indexes + # seem correct. + for expected, ty in enumerate(utility_types): + got = lower_extra_type(ty) + assert got == expected, "Wrong index when lowering" + + # Lower interfaces in the order of the IID phf's entries lookup. + for iface in iid_phf.entries: + lower_iface(iface) + + # Write out the final output files + fd.write("/* THIS FILE WAS GENERATED BY xptcodegen.py - DO NOT EDIT */\n\n") + header_fd.write("/* THIS FILE WAS GENERATED BY xptcodegen.py - DO NOT EDIT */\n\n") + + header_fd.write( + """ +#ifndef xptdata_h +#define xptdata_h + +enum class nsXPTInterface : uint16_t { +""" + ) + + for entry in iid_phf.entries: + header_fd.write(" %s,\n" % entry["name"]) + + header_fd.write( + """ +}; + +#endif +""" + ) + + # Include any bindings files which we need to include for webidl types + for include in sorted(includes): + fd.write('#include "%s"\n' % include) + + # Write out our header + fd.write( + """ +#include "xptinfo.h" +#include "mozilla/PerfectHash.h" +#include "mozilla/dom/BindingUtils.h" + +// These template methods are specialized to be used in the sDOMObjects table. +template<mozilla::dom::prototypes::ID PrototypeID, typename T> +static nsresult UnwrapDOMObject(JS::Handle<JS::Value> aHandle, void** aObj, JSContext* aCx) +{ + RefPtr<T> p; + nsresult rv = mozilla::dom::UnwrapObject<PrototypeID, T>(aHandle, p, aCx); + p.forget(aObj); + return rv; +} + +template<typename T> +static bool WrapDOMObject(JSContext* aCx, void* aObj, JS::MutableHandle<JS::Value> aHandle) +{ + return mozilla::dom::GetOrCreateDOMReflector(aCx, reinterpret_cast<T*>(aObj), aHandle); +} + +template<typename T> +static void CleanupDOMObject(void* aObj) +{ + RefPtr<T> p = already_AddRefed<T>(reinterpret_cast<T*>(aObj)); +} + +namespace xpt { +namespace detail { + +""" + ) + + # Static data arrays + def array(ty, name, els): + fd.write( + "const %s %s[] = {%s\n};\n\n" + % (ty, name, ",".join(indented("\n" + str(e)) for e in els)) + ) + + array("nsXPTType", "sTypes", types) + array("nsXPTParamInfo", "sParams", params) + array("nsXPTMethodInfo", "sMethods", methods) + # Verify that stack-allocated buffers will do for xptcall implementations. + msg = ( + "Too many method arguments in %s. " + "Either reduce the number of arguments " + "or increase PARAM_BUFFER_COUNT." % method_with_max_params + ) + fd.write('static_assert(%s <= PARAM_BUFFER_COUNT, "%s");\n\n' % (max_params, msg)) + array("nsXPTDOMObjectInfo", "sDOMObjects", domobjects) + array("nsXPTConstantInfo", "sConsts", consts) + + # The strings array. We write out individual characters to avoid MSVC restrictions. + fd.write("const char sStrings[] = {\n") + for s, off in strings.items(): + fd.write(" // %d = %s\n '%s','\\0',\n" % (off, s, "','".join(s))) + fd.write("};\n\n") + + # Build the perfect hash table for InterfaceByIID + fd.write( + iid_phf.cxx_codegen( + name="InterfaceByIID", + entry_type="nsXPTInterfaceInfo", + entries_name="sInterfaces", + lower_entry=lambda iface: iface["cxx"], + # Check that the IIDs match to support IID keys not in the map. + return_type="const nsXPTInterfaceInfo*", + return_entry="return entry.IID().Equals(aKey) ? &entry : nullptr;", + key_type="const nsIID&", + key_bytes="reinterpret_cast<const char*>(&aKey)", + key_length="sizeof(nsIID)", + ) + ) + fd.write("\n") + + # Build the perfect hash table for InterfaceByName + fd.write( + name_phf.cxx_codegen( + name="InterfaceByName", + entry_type="uint16_t", + lower_entry=lambda iface: "%-4d /* %s */" % (iface["idx"], iface["name"]), + # Get the actual nsXPTInterfaceInfo from sInterfaces, and + # double-check that names match. + return_type="const nsXPTInterfaceInfo*", + return_entry="return strcmp(sInterfaces[entry].Name(), aKey) == 0" + " ? &sInterfaces[entry] : nullptr;", + ) + ) + fd.write("\n") + + # Generate some checks that the indexes for the utility types match the + # declared ones in xptinfo.h + for idx, ty in enumerate(utility_types): + fd.write( + 'static_assert(%d == (uint8_t)nsXPTType::Idx::%s, "Bad idx");\n' + % (idx, ty["tag"][3:]) + ) + + fd.write( + """ +const uint16_t sInterfacesSize = mozilla::ArrayLength(sInterfaces); + +} // namespace detail +} // namespace xpt +""" + ) + + +def link_and_write(files, outfile, outheader): + interfaces = [] + for file in files: + with open(file, "r") as fd: + interfaces += json.load(fd) + + iids = set() + names = set() + for interface in interfaces: + assert interface["uuid"] not in iids, "duplicated UUID %s" % interface["uuid"] + assert interface["name"] not in names, "duplicated name %s" % interface["name"] + iids.add(interface["uuid"]) + names.add(interface["name"]) + + link_to_cpp(interfaces, outfile, outheader) + + +def main(): + import sys + from argparse import ArgumentParser + + parser = ArgumentParser() + parser.add_argument("outfile", help="Output C++ file to generate") + parser.add_argument("outheader", help="Output C++ header file to generate") + parser.add_argument("xpts", nargs="*", help="source xpt files") + + args = parser.parse_args(sys.argv[1:]) + with open(args.outfile, "w") as fd, open(args.outheader, "w") as header_fd: + link_and_write(args.xpts, fd, header_fd) + + +if __name__ == "__main__": + main() diff --git a/xpcom/reflect/xptinfo/xptinfo.cpp b/xpcom/reflect/xptinfo/xptinfo.cpp new file mode 100644 index 0000000000..c44e97cad4 --- /dev/null +++ b/xpcom/reflect/xptinfo/xptinfo.cpp @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "xptinfo.h" +#include "nsISupports.h" +#include "mozilla/dom/DOMJSClass.h" +#include "mozilla/dom/BindingUtils.h" +#include "mozilla/ArrayUtils.h" + +#include "jsfriendapi.h" +#include "js/Symbol.h" + +using namespace mozilla; +using namespace mozilla::dom; +using namespace xpt::detail; + +//////////////////////////////////// +// Constant Lookup Helper Methods // +//////////////////////////////////// + +bool nsXPTInterfaceInfo::HasAncestor(const nsIID& aIID) const { + for (const auto* info = this; info; info = info->GetParent()) { + if (info->IID() == aIID) { + return true; + } + } + return false; +} + +const nsXPTConstantInfo& nsXPTInterfaceInfo::Constant(uint16_t aIndex) const { + MOZ_ASSERT(aIndex < ConstantCount()); + + if (const nsXPTInterfaceInfo* pi = GetParent()) { + if (aIndex < pi->ConstantCount()) { + return pi->Constant(aIndex); + } + aIndex -= pi->ConstantCount(); + } + + return xpt::detail::GetConstant(mConsts + aIndex); +} + +const nsXPTMethodInfo& nsXPTInterfaceInfo::Method(uint16_t aIndex) const { + MOZ_ASSERT(aIndex < MethodCount()); + + if (const nsXPTInterfaceInfo* pi = GetParent()) { + if (aIndex < pi->MethodCount()) { + return pi->Method(aIndex); + } + aIndex -= pi->MethodCount(); + } + + return xpt::detail::GetMethod(mMethods + aIndex); +} + +nsresult nsXPTInterfaceInfo::GetMethodInfo( + uint16_t aIndex, const nsXPTMethodInfo** aInfo) const { + *aInfo = aIndex < MethodCount() ? &Method(aIndex) : nullptr; + return *aInfo ? NS_OK : NS_ERROR_FAILURE; +} + +nsresult nsXPTInterfaceInfo::GetConstant(uint16_t aIndex, + JS::MutableHandle<JS::Value> aConstant, + char** aName) const { + if (aIndex < ConstantCount()) { + aConstant.set(Constant(aIndex).JSValue()); + *aName = moz_xstrdup(Constant(aIndex).Name()); + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +//////////////////////////////////// +// nsXPTMethodInfo symbol helpers // +//////////////////////////////////// + +const char* nsXPTMethodInfo::SymbolDescription() const { + switch (GetSymbolCode()) { +#define XPC_WELL_KNOWN_SYMBOL_DESCR_CASE(name) \ + case JS::SymbolCode::name: \ + return #name; + JS_FOR_EACH_WELL_KNOWN_SYMBOL(XPC_WELL_KNOWN_SYMBOL_DESCR_CASE) +#undef XPC_WELL_KNOWN_SYMBOL_DESCR_CASE + + default: + return ""; + } +} + +bool nsXPTMethodInfo::GetId(JSContext* aCx, jsid& aId) const { + if (IsSymbol()) { + aId = JS::PropertyKey::Symbol(GetSymbol(aCx)); + return true; + } + + JSString* str = JS_AtomizeString(aCx, Name()); + if (!str) { + return false; + } + aId = JS::PropertyKey::NonIntAtom(str); + return true; +} diff --git a/xpcom/reflect/xptinfo/xptinfo.h b/xpcom/reflect/xptinfo/xptinfo.h new file mode 100644 index 0000000000..2456c2c2b5 --- /dev/null +++ b/xpcom/reflect/xptinfo/xptinfo.h @@ -0,0 +1,711 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +/** + * Structures and methods with information about XPCOM interfaces for use by + * XPConnect. The static backing data structures used by this file are generated + * from xpidl interfaces by the jsonxpt.py and xptcodegen.py scripts. + */ + +#ifndef xptinfo_h +#define xptinfo_h + +#include <stdint.h> +#include "nsID.h" +#include "mozilla/Assertions.h" +#include "jsapi.h" +#include "js/Symbol.h" +#include "js/Value.h" +#include "nsString.h" +#include "nsTArray.h" + +// Forward Declarations +namespace mozilla { +namespace dom { +struct NativePropertyHooks; +} // namespace dom +} // namespace mozilla + +struct nsXPTInterfaceInfo; +struct nsXPTType; +struct nsXPTParamInfo; +struct nsXPTMethodInfo; +struct nsXPTConstantInfo; +struct nsXPTDOMObjectInfo; + +enum class nsXPTInterface : uint16_t; + +// Internal helper methods. +namespace xpt { +namespace detail { + +inline const nsXPTInterfaceInfo* GetInterface(uint16_t aIndex); +inline const nsXPTType& GetType(uint16_t aIndex); +inline const nsXPTParamInfo& GetParam(uint16_t aIndex); +inline const nsXPTMethodInfo& GetMethod(uint16_t aIndex); +inline const nsXPTConstantInfo& GetConstant(uint16_t aIndex); +inline const nsXPTDOMObjectInfo& GetDOMObjectInfo(uint16_t aIndex); +inline const char* GetString(uint32_t aIndex); + +const nsXPTInterfaceInfo* InterfaceByIID(const nsIID& aIID); +const nsXPTInterfaceInfo* InterfaceByName(const char* aName); + +extern const uint16_t sInterfacesSize; + +} // namespace detail +} // namespace xpt + +/* + * An Interface describes a single XPCOM interface, including all of its + * methods. We don't record non-scriptable interfaces. + */ +struct nsXPTInterfaceInfo { + // High efficiency getters for Interfaces based on perfect hashes. + static const nsXPTInterfaceInfo* ByIID(const nsIID& aIID) { + return xpt::detail::InterfaceByIID(aIID); + } + static const nsXPTInterfaceInfo* ByName(const char* aName) { + return xpt::detail::InterfaceByName(aName); + } + + static const nsXPTInterfaceInfo* Get(nsXPTInterface aID) { + return ByIndex(uint16_t(aID)); + } + + // These are only needed for Components_interfaces's enumerator. + static const nsXPTInterfaceInfo* ByIndex(uint16_t aIndex) { + // NOTE: We add 1 here, as the internal index 0 is reserved for null. + return xpt::detail::GetInterface(aIndex + 1); + } + static uint16_t InterfaceCount() { return xpt::detail::sInterfacesSize; } + + // Interface flag getters + bool IsFunction() const { return mFunction; } + bool IsBuiltinClass() const { return mBuiltinClass; } + bool IsMainProcessScriptableOnly() const { + return mMainProcessScriptableOnly; + } + + const char* Name() const { return xpt::detail::GetString(mName); } + const nsIID& IID() const { return mIID; } + + // Get the parent interface, or null if this interface doesn't have a parent. + const nsXPTInterfaceInfo* GetParent() const { + return xpt::detail::GetInterface(mParent); + } + + // Do we have an ancestor interface with the given IID? + bool HasAncestor(const nsIID& aIID) const; + + // Get methods & constants + uint16_t ConstantCount() const { return mNumConsts; } + const nsXPTConstantInfo& Constant(uint16_t aIndex) const; + uint16_t MethodCount() const { return mNumMethods; } + const nsXPTMethodInfo& Method(uint16_t aIndex) const; + + nsresult GetMethodInfo(uint16_t aIndex, const nsXPTMethodInfo** aInfo) const; + nsresult GetConstant(uint16_t aIndex, JS::MutableHandle<JS::Value> constant, + char** aName) const; + + //////////////////////////////////////////////////////////////// + // Ensure these fields are in the same order as xptcodegen.py // + //////////////////////////////////////////////////////////////// + + nsID mIID; + uint32_t mName; // Index into xpt::detail::sStrings + + uint16_t mParent : 14; + uint16_t mBuiltinClass : 1; + // XXX(nika): Do we need this if we don't have addons anymore? + uint16_t mMainProcessScriptableOnly : 1; + + uint16_t mMethods; // Index into xpt::detail::sMethods + + uint16_t mConsts : 14; // Index into xpt::detail::sConsts + uint16_t mFunction : 1; + // uint16_t unused : 1; + + uint8_t mNumMethods; // NOTE(24/04/18): largest=nsIDocShell (193) + uint8_t mNumConsts; // NOTE(24/04/18): largest=nsIAccessibleRole (175) +}; + +// The fields in nsXPTInterfaceInfo were carefully ordered to minimize size. +static_assert(sizeof(nsXPTInterfaceInfo) == 28, "wrong size?"); + +/* + * The following enum represents contains the different tag types which + * can be found in nsXPTTypeInfo::mTag. + * + * WARNING: mTag is 5 bits wide, supporting at most 32 tags. + */ +enum nsXPTTypeTag : uint8_t { + // Arithmetic (POD) Types + // - Do not require cleanup, + // - All bit patterns are valid, + // - Outparams may be uninitialized by caller, + // - Directly supported in xptcall. + // + // NOTE: The name 'Arithmetic' comes from Harbison/Steele. Despite being a tad + // unclear, it is used frequently in xptcall, so is unlikely to be changed. + TD_INT8 = 0, + TD_INT16 = 1, + TD_INT32 = 2, + TD_INT64 = 3, + TD_UINT8 = 4, + TD_UINT16 = 5, + TD_UINT32 = 6, + TD_UINT64 = 7, + TD_FLOAT = 8, + TD_DOUBLE = 9, + TD_BOOL = 10, + TD_CHAR = 11, + TD_WCHAR = 12, + _TD_LAST_ARITHMETIC = TD_WCHAR, + + // Pointer Types + // - Require cleanup unless NULL, + // - All-zeros (NULL) bit pattern is valid, + // - Outparams may be uninitialized by caller, + // - Supported in xptcall as raw pointer. + TD_VOID = 13, + TD_NSIDPTR = 14, + TD_PSTRING = 15, + TD_PWSTRING = 16, + TD_INTERFACE_TYPE = 17, + TD_INTERFACE_IS_TYPE = 18, + TD_LEGACY_ARRAY = 19, + TD_PSTRING_SIZE_IS = 20, + TD_PWSTRING_SIZE_IS = 21, + TD_DOMOBJECT = 22, + TD_PROMISE = 23, + _TD_LAST_POINTER = TD_PROMISE, + + // Complex Types + // - Require cleanup, + // - Always passed indirectly, + // - Outparams must be initialized by caller, + // - Supported in xptcall due to indirection. + TD_UTF8STRING = 24, + TD_CSTRING = 25, + TD_ASTRING = 26, + TD_NSID = 27, + TD_JSVAL = 28, + TD_ARRAY = 29, + _TD_LAST_COMPLEX = TD_ARRAY +}; + +static_assert(_TD_LAST_COMPLEX < 32, "nsXPTTypeTag must fit in 5 bits"); + +/* + * A nsXPTType is a union used to identify the type of a method argument or + * return value. The internal data is stored as an 5-bit tag, and two 8-bit + * integers, to keep alignment requirements low. + * + * nsXPTType contains 3 extra bits, reserved for use by nsXPTParamInfo. + */ +struct nsXPTType { + nsXPTTypeTag Tag() const { return static_cast<nsXPTTypeTag>(mTag); } + + // The index in the function argument list which should be used when + // determining the iid_is or size_is properties of this dependent type. + uint8_t ArgNum() const { + MOZ_ASSERT(Tag() == TD_INTERFACE_IS_TYPE || Tag() == TD_PSTRING_SIZE_IS || + Tag() == TD_PWSTRING_SIZE_IS || Tag() == TD_LEGACY_ARRAY); + return mData1; + } + + private: + // Helper for reading 16-bit data values split between mData1 and mData2. + uint16_t Data16() const { + return static_cast<uint16_t>(mData1 << 8) | mData2; + } + + public: + // Get the type of the element in the current array or sequence. Arrays only + // fit 8 bits of type data, while sequences support up to 16 bits of type data + // due to not needing to store an ArgNum. + const nsXPTType& ArrayElementType() const { + if (Tag() == TD_LEGACY_ARRAY) { + return xpt::detail::GetType(mData2); + } + MOZ_ASSERT(Tag() == TD_ARRAY); + return xpt::detail::GetType(Data16()); + } + + // We store the 16-bit iface value as two 8-bit values in order to + // avoid 16-bit alignment requirements for XPTTypeDescriptor, which + // reduces its size and also the size of XPTParamDescriptor. + const nsXPTInterfaceInfo* GetInterface() const { + MOZ_ASSERT(Tag() == TD_INTERFACE_TYPE); + return xpt::detail::GetInterface(Data16()); + } + + const nsXPTDOMObjectInfo& GetDOMObjectInfo() const { + MOZ_ASSERT(Tag() == TD_DOMOBJECT); + return xpt::detail::GetDOMObjectInfo(Data16()); + } + + // See the comments in nsXPTTypeTag for an explanation as to what each of + // these categories mean. + bool IsArithmetic() const { return Tag() <= _TD_LAST_ARITHMETIC; } + bool IsPointer() const { + return !IsArithmetic() && Tag() <= _TD_LAST_POINTER; + } + bool IsComplex() const { return Tag() > _TD_LAST_POINTER; } + + bool IsInterfacePointer() const { + return Tag() == TD_INTERFACE_TYPE || Tag() == TD_INTERFACE_IS_TYPE; + } + + bool IsDependent() const { + return (Tag() == TD_ARRAY && InnermostType().IsDependent()) || + Tag() == TD_INTERFACE_IS_TYPE || Tag() == TD_LEGACY_ARRAY || + Tag() == TD_PSTRING_SIZE_IS || Tag() == TD_PWSTRING_SIZE_IS; + } + + // Unwrap a nested type to its innermost value (e.g. through arrays). + const nsXPTType& InnermostType() const { + if (Tag() == TD_LEGACY_ARRAY || Tag() == TD_ARRAY) { + return ArrayElementType().InnermostType(); + } + return *this; + } + + // In-memory size of native type in bytes. + inline size_t Stride() const; + + // Offset the given base pointer to reference the element at the given index. + void* ElementPtr(const void* aBase, uint32_t aIndex) const { + return (char*)aBase + (aIndex * Stride()); + } + + // Zero out a native value of the given type. The type must not be 'complex'. + void ZeroValue(void* aValue) const { + MOZ_RELEASE_ASSERT(!IsComplex(), "Cannot zero a complex value"); + memset(aValue, 0, Stride()); + } + + // Indexes into the extra types array of a small set of known types. + enum class Idx : uint8_t { + INT8 = 0, + UINT8, + INT16, + UINT16, + INT32, + UINT32, + INT64, + UINT64, + FLOAT, + DOUBLE, + BOOL, + CHAR, + WCHAR, + NSIDPTR, + PSTRING, + PWSTRING, + INTERFACE_IS_TYPE + }; + + // Helper methods for fabricating nsXPTType values used by xpconnect. + static nsXPTType MkArrayType(Idx aInner) { + MOZ_ASSERT(aInner <= Idx::INTERFACE_IS_TYPE); + return {TD_LEGACY_ARRAY, false, false, false, 0, (uint8_t)aInner}; + } + static const nsXPTType& Get(Idx aInner) { + MOZ_ASSERT(aInner <= Idx::INTERFACE_IS_TYPE); + return xpt::detail::GetType((uint8_t)aInner); + } + + /////////////////////////////////////// + // nsXPTType backwards compatibility // + /////////////////////////////////////// + + nsXPTType& operator=(nsXPTTypeTag aPrefix) { + mTag = aPrefix; + return *this; + } + operator nsXPTTypeTag() const { return Tag(); } + +#define TD_ALIAS_(name_, value_) static constexpr nsXPTTypeTag name_ = value_ + TD_ALIAS_(T_I8, TD_INT8); + TD_ALIAS_(T_I16, TD_INT16); + TD_ALIAS_(T_I32, TD_INT32); + TD_ALIAS_(T_I64, TD_INT64); + TD_ALIAS_(T_U8, TD_UINT8); + TD_ALIAS_(T_U16, TD_UINT16); + TD_ALIAS_(T_U32, TD_UINT32); + TD_ALIAS_(T_U64, TD_UINT64); + TD_ALIAS_(T_FLOAT, TD_FLOAT); + TD_ALIAS_(T_DOUBLE, TD_DOUBLE); + TD_ALIAS_(T_BOOL, TD_BOOL); + TD_ALIAS_(T_CHAR, TD_CHAR); + TD_ALIAS_(T_WCHAR, TD_WCHAR); + TD_ALIAS_(T_VOID, TD_VOID); + TD_ALIAS_(T_NSIDPTR, TD_NSIDPTR); + TD_ALIAS_(T_CHAR_STR, TD_PSTRING); + TD_ALIAS_(T_WCHAR_STR, TD_PWSTRING); + TD_ALIAS_(T_INTERFACE, TD_INTERFACE_TYPE); + TD_ALIAS_(T_INTERFACE_IS, TD_INTERFACE_IS_TYPE); + TD_ALIAS_(T_LEGACY_ARRAY, TD_LEGACY_ARRAY); + TD_ALIAS_(T_PSTRING_SIZE_IS, TD_PSTRING_SIZE_IS); + TD_ALIAS_(T_PWSTRING_SIZE_IS, TD_PWSTRING_SIZE_IS); + TD_ALIAS_(T_UTF8STRING, TD_UTF8STRING); + TD_ALIAS_(T_CSTRING, TD_CSTRING); + TD_ALIAS_(T_ASTRING, TD_ASTRING); + TD_ALIAS_(T_NSID, TD_NSID); + TD_ALIAS_(T_JSVAL, TD_JSVAL); + TD_ALIAS_(T_DOMOBJECT, TD_DOMOBJECT); + TD_ALIAS_(T_PROMISE, TD_PROMISE); + TD_ALIAS_(T_ARRAY, TD_ARRAY); +#undef TD_ALIAS_ + + //////////////////////////////////////////////////////////////// + // Ensure these fields are in the same order as xptcodegen.py // + //////////////////////////////////////////////////////////////// + + uint8_t mTag : 5; + + // Parameter bitflags are packed into the XPTTypeDescriptor to save space. + // When the TypeDescriptor is not in a parameter, these flags are ignored. + uint8_t mInParam : 1; + uint8_t mOutParam : 1; + uint8_t mOptionalParam : 1; + + // The data for the different variants is stored in these two data fields. + // These should only be accessed via the getter methods above, which will + // assert if the tag is invalid. + uint8_t mData1; + uint8_t mData2; +}; + +// The fields in nsXPTType were carefully ordered to minimize size. +static_assert(sizeof(nsXPTType) == 3, "wrong size"); + +/* + * A nsXPTParamInfo is used to describe either a single argument to a method or + * a method's result. It stores its flags in the type descriptor to save space. + */ +struct nsXPTParamInfo { + bool IsIn() const { return mType.mInParam; } + bool IsOut() const { return mType.mOutParam; } + bool IsOptional() const { return mType.mOptionalParam; } + bool IsShared() const { return false; } // XXX remove (backcompat) + + // Get the type of this parameter. + const nsXPTType& Type() const { return mType; } + const nsXPTType& GetType() const { + return Type(); + } // XXX remove (backcompat) + + // Whether this parameter is passed indirectly on the stack. All out/inout + // params are passed indirectly, and complex types are always passed + // indirectly. + bool IsIndirect() const { return IsOut() || Type().IsComplex(); } + + //////////////////////////////////////////////////////////////// + // Ensure these fields are in the same order as xptcodegen.py // + //////////////////////////////////////////////////////////////// + + nsXPTType mType; +}; + +// The fields in nsXPTParamInfo were carefully ordered to minimize size. +static_assert(sizeof(nsXPTParamInfo) == 3, "wrong size"); + +/* + * A nsXPTMethodInfo is used to describe a single interface method. + */ +struct nsXPTMethodInfo { + bool IsGetter() const { return mGetter; } + bool IsSetter() const { return mSetter; } + bool IsReflectable() const { return mReflectable; } + bool IsSymbol() const { return mIsSymbol; } + bool WantsOptArgc() const { return mOptArgc; } + bool WantsContext() const { return mContext; } + uint8_t ParamCount() const { return mNumParams; } + + const char* Name() const { + MOZ_ASSERT(!IsSymbol()); + return xpt::detail::GetString(mName); + } + const nsXPTParamInfo& Param(uint8_t aIndex) const { + MOZ_ASSERT(aIndex < mNumParams); + return xpt::detail::GetParam(mParams + aIndex); + } + + bool HasRetval() const { return mHasRetval; } + const nsXPTParamInfo* GetRetval() const { + return mHasRetval ? &Param(mNumParams - 1) : nullptr; + } + + // If this is an [implicit_jscontext] method, returns the index of the + // implicit JSContext* argument in the C++ method's argument list. + // Otherwise returns UINT8_MAX. + uint8_t IndexOfJSContext() const { + if (!WantsContext()) { + return UINT8_MAX; + } + if (IsGetter() || IsSetter()) { + // Getters/setters always have the context as first argument. + return 0; + } + // The context comes before the return value, if there is one. + MOZ_ASSERT_IF(HasRetval(), ParamCount() > 0); + return ParamCount() - uint8_t(HasRetval()); + } + + JS::SymbolCode GetSymbolCode() const { + MOZ_ASSERT(IsSymbol()); + return JS::SymbolCode(mName); + } + + JS::Symbol* GetSymbol(JSContext* aCx) const { + return JS::GetWellKnownSymbol(aCx, GetSymbolCode()); + } + + const char* SymbolDescription() const; + + const char* NameOrDescription() const { + if (IsSymbol()) { + return SymbolDescription(); + } + return Name(); + } + + bool GetId(JSContext* aCx, jsid& aId) const; + + ///////////////////////////////////////////// + // nsXPTMethodInfo backwards compatibility // + ///////////////////////////////////////////// + + const char* GetName() const { return Name(); } + + uint8_t GetParamCount() const { return ParamCount(); } + const nsXPTParamInfo& GetParam(uint8_t aIndex) const { return Param(aIndex); } + + //////////////////////////////////////////////////////////////// + // Ensure these fields are in the same order as xptcodegen.py // + //////////////////////////////////////////////////////////////// + + uint32_t mName; // Index into xpt::detail::sStrings. + uint16_t mParams; // Index into xpt::detail::sParams. + uint8_t mNumParams; + + uint8_t mGetter : 1; + uint8_t mSetter : 1; + uint8_t mReflectable : 1; + uint8_t mOptArgc : 1; + uint8_t mContext : 1; + uint8_t mHasRetval : 1; + uint8_t mIsSymbol : 1; +}; + +// The fields in nsXPTMethodInfo were carefully ordered to minimize size. +static_assert(sizeof(nsXPTMethodInfo) == 8, "wrong size"); + +// This number is chosen to be no larger than the maximum number of parameters +// any XPIDL-defined function needs; there is a static assert in the generated +// code from xptcodegen.py to verify that decision. It is therefore also the +// maximum number of stack allocated nsXPTCMiniVariant structures for argument +// passing purposes in PrepareAndDispatch implementations. +#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE) +# define PARAM_BUFFER_COUNT 18 +#else +# define PARAM_BUFFER_COUNT 14 +#endif + +/** + * A nsXPTConstantInfo is used to describe a single interface constant. + */ +struct nsXPTConstantInfo { + const char* Name() const { return xpt::detail::GetString(mName); } + + JS::Value JSValue() const { + if (mSigned || mValue <= uint32_t(INT32_MAX)) { + return JS::Int32Value(int32_t(mValue)); + } + return JS::DoubleValue(mValue); + } + + //////////////////////////////////////////////////////////////// + // Ensure these fields are in the same order as xptcodegen.py // + //////////////////////////////////////////////////////////////// + + uint32_t mName : 31; // Index into xpt::detail::mStrings. + + // Whether the value should be interpreted as a int32_t or uint32_t. + uint32_t mSigned : 1; + uint32_t mValue; // The value stored as a u32 +}; + +// The fields in nsXPTConstantInfo were carefully ordered to minimize size. +static_assert(sizeof(nsXPTConstantInfo) == 8, "wrong size"); + +/** + * Object representing the information required to wrap and unwrap DOMObjects. + * + * This object will not live in rodata as it contains relocations. + */ +struct nsXPTDOMObjectInfo { + nsresult Unwrap(JS::Handle<JS::Value> aHandle, void** aObj, + JSContext* aCx) const { + return mUnwrap(aHandle, aObj, aCx); + } + + bool Wrap(JSContext* aCx, void* aObj, + JS::MutableHandle<JS::Value> aHandle) const { + return mWrap(aCx, aObj, aHandle); + } + + void Cleanup(void* aObj) const { return mCleanup(aObj); } + + //////////////////////////////////////////////////////////////// + // Ensure these fields are in the same order as xptcodegen.py // + //////////////////////////////////////////////////////////////// + + nsresult (*mUnwrap)(JS::Handle<JS::Value> aHandle, void** aObj, + JSContext* aCx); + bool (*mWrap)(JSContext* aCx, void* aObj, + JS::MutableHandle<JS::Value> aHandle); + void (*mCleanup)(void* aObj); +}; + +namespace xpt { +namespace detail { + +// The UntypedTArray type allows low-level access from XPConnect to nsTArray +// internals without static knowledge of the array element type in question. +class UntypedTArray : public nsTArray_base<nsTArrayFallibleAllocator, + nsTArray_RelocateUsingMemutils> { + public: + void* Elements() const { return static_cast<void*>(Hdr() + 1); } + + // Changes the length and capacity to be at least large enough for aTo + // elements. + bool SetLength(const nsXPTType& aEltTy, uint32_t aTo) { + if (!EnsureCapacity<nsTArrayFallibleAllocator>(aTo, aEltTy.Stride())) { + return false; + } + + if (mHdr != EmptyHdr()) { + mHdr->mLength = aTo; + } + + return true; + } + + // Free backing memory for the nsTArray object. + void Clear() { + if (mHdr != EmptyHdr() && !UsesAutoArrayBuffer()) { + nsTArrayFallibleAllocator::Free(mHdr); + } + mHdr = EmptyHdr(); + } +}; + +////////////////////////////////////////////// +// Raw typelib data stored in const statics // +////////////////////////////////////////////// + +// XPIDL information +extern const nsXPTInterfaceInfo sInterfaces[]; +extern const nsXPTType sTypes[]; +extern const nsXPTParamInfo sParams[]; +extern const nsXPTMethodInfo sMethods[]; +extern const nsXPTConstantInfo sConsts[]; +extern const nsXPTDOMObjectInfo sDOMObjects[]; + +extern const char sStrings[]; + +////////////////////////////////////// +// Helper Methods for fetching data // +////////////////////////////////////// + +inline const nsXPTInterfaceInfo* GetInterface(uint16_t aIndex) { + if (aIndex > 0 && aIndex <= sInterfacesSize) { + return &sInterfaces[aIndex - 1]; // 1-based as 0 is a marker. + } + return nullptr; +} + +inline const nsXPTType& GetType(uint16_t aIndex) { return sTypes[aIndex]; } + +inline const nsXPTParamInfo& GetParam(uint16_t aIndex) { + return sParams[aIndex]; +} + +inline const nsXPTMethodInfo& GetMethod(uint16_t aIndex) { + return sMethods[aIndex]; +} + +inline const nsXPTConstantInfo& GetConstant(uint16_t aIndex) { + return sConsts[aIndex]; +} + +inline const nsXPTDOMObjectInfo& GetDOMObjectInfo(uint16_t aIndex) { + return sDOMObjects[aIndex]; +} + +inline const char* GetString(uint32_t aIndex) { return &sStrings[aIndex]; } + +} // namespace detail +} // namespace xpt + +#define XPT_FOR_EACH_ARITHMETIC_TYPE(MACRO) \ + MACRO(TD_INT8, int8_t) \ + MACRO(TD_INT16, int16_t) \ + MACRO(TD_INT32, int32_t) \ + MACRO(TD_INT64, int64_t) \ + MACRO(TD_UINT8, uint8_t) \ + MACRO(TD_UINT16, uint16_t) \ + MACRO(TD_UINT32, uint32_t) \ + MACRO(TD_UINT64, uint64_t) \ + MACRO(TD_FLOAT, float) \ + MACRO(TD_DOUBLE, double) \ + MACRO(TD_BOOL, bool) \ + MACRO(TD_CHAR, char) \ + MACRO(TD_WCHAR, char16_t) + +#define XPT_FOR_EACH_POINTER_TYPE(MACRO) \ + MACRO(TD_VOID, void*) \ + MACRO(TD_NSIDPTR, nsID*) \ + MACRO(TD_PSTRING, char*) \ + MACRO(TD_PWSTRING, wchar_t*) \ + MACRO(TD_INTERFACE_TYPE, nsISupports*) \ + MACRO(TD_INTERFACE_IS_TYPE, nsISupports*) \ + MACRO(TD_LEGACY_ARRAY, void*) \ + MACRO(TD_PSTRING_SIZE_IS, char*) \ + MACRO(TD_PWSTRING_SIZE_IS, wchar_t*) \ + MACRO(TD_DOMOBJECT, void*) \ + MACRO(TD_PROMISE, mozilla::dom::Promise*) + +#define XPT_FOR_EACH_COMPLEX_TYPE(MACRO) \ + MACRO(TD_UTF8STRING, nsCString) \ + MACRO(TD_CSTRING, nsCString) \ + MACRO(TD_ASTRING, nsString) \ + MACRO(TD_NSID, nsID) \ + MACRO(TD_JSVAL, JS::Value) \ + MACRO(TD_ARRAY, xpt::detail::UntypedTArray) + +#define XPT_FOR_EACH_TYPE(MACRO) \ + XPT_FOR_EACH_ARITHMETIC_TYPE(MACRO) \ + XPT_FOR_EACH_POINTER_TYPE(MACRO) \ + XPT_FOR_EACH_COMPLEX_TYPE(MACRO) + +inline size_t nsXPTType::Stride() const { + // Compute the stride to use when walking an array of the given type. + switch (Tag()) { +#define XPT_TYPE_STRIDE(tag, type) \ + case tag: \ + return sizeof(type); + XPT_FOR_EACH_TYPE(XPT_TYPE_STRIDE) +#undef XPT_TYPE_STRIDE + } + + MOZ_CRASH("Unknown type"); +} + +#endif /* xptinfo_h */ |